Vue3 导出word代码,可导出数据+图片

214次阅读
没有评论

共计 3324 个字符,预计需要花费 9 分钟才能阅读完成。

网上搜到的代码都没办法直接使用,需要修改后才能用,我在这里发一版修改后的完美可用的代码,可以直接拿去用,也给自己留个备份。

我在使用网上搜到的代码的时候遇到一些问题,如果你也遇到了这些问题,那么表示这篇文章可以帮助你。

 

问题:

1、JSZIP 版本太高 (V3.x),导致 docxtemplater 无法使用,以及一些函数大改动。

2、Vue3 使用的 Vite 而不是 Webpack,因此 require,Buffer 等功能不能使用。

 

解决方法:

1、手动将 JSZIP 由 3.x 改为 2.3.0 版本,重新 npm i,即可解决。

2、Buffer 要安装 buffer 依赖,使用

npm i buffer --save

进行安装,然后直接按如下引用:

import {Buffer} from "buffer";

另外,网络上的代码在加载图片处理依赖时使用的是

var ImageModule = require('docxtemplater-image-module-free');

需要改为

import ImageModule from "docxtemplater-image-module-free";

 

以上就是主要的问题所在,下面贴上完整代码和一些需要注意的东西。

完整代码

1、开始之前,你需要先安装如下依赖

-- 安装 docxtemplater
npm install docxtemplater pizzip  --save

-- 安装 jszip-utils
npm install jszip-utils --save 

-- 安装 jszip
npm install jszip --save

-- 安装 FileSaver
npm install file-saver --save

-- 安装 buffer 用作 b64 转 buffer
npm install buffer --save

-- 安装 docxtemplater-image-module-free 用作图片处理
npm install docxtemplater-image-module-free --save

 

2、新建一个 js 文件,我是在 /src/utils/ 下新建的 fileExport.js,并粘贴如下内容。

import PizZip from 'jszip';
import docxtemplater from 'docxtemplater';
import JSZipUtils from 'jszip-utils';
import {saveAs} from 'file-saver';
import {Buffer} from "buffer";
import ImageModule from "docxtemplater-image-module-free";

const base64DataURLToArrayBuffer = (dataURL) => {const base64Regex = /^data:image\/(png|jpg|svg|svg\+xml);base64,/;
    if (!base64Regex.test(dataURL)) {return false;}
    const stringBase64 = dataURL.replace(base64Regex, "");
    let binaryString;
    if (typeof window !== "undefined") {binaryString = window.atob(stringBase64);
    } else {binaryString = new Buffer(stringBase64, "base64").toString("binary");
    }
    const len = binaryString.length;
    const bytes = new Uint8Array(len);
    for (let i = 0; i < len; i++) {const ascii = binaryString.charCodeAt(i);
        bytes[i] = ascii;
    }
    return bytes.buffer;
}

/**
 * 导出 word, 支持图片
 * @param {Object} tempDocxPath 模板文件路径
 * @param {Object} wordData 导出数据
 * @param {Object} fileName 导出文件名
 */
export const exportWord = (tempDocxPath, wordData, fileName, imageSize = {}) => {
    // 读取并获得模板文件的二进制内容
    JSZipUtils.getBinaryContent(tempDocxPath, function (error, content) {if (error) {throw error;}
            let opts = {};
            opts.centered = true; // 图片居中,在 word 模板中定义方式为 {%%image}
            opts.fileType = "docx";
            opts.getImage = function (chartId) {return base64DataURLToArrayBuffer(chartId);
            };
            opts.getSize = function (img, tagValue, tagName) {// console.log(img);//ArrayBuffer 数据
                // console.log(tagValue);//base64 数据
                // console.log(tagName);//wordData 对象的图像属性名
                // 自定义指定图像大小
                // eslint-disable-next-line no-prototype-builtins
                if (imageSize.hasOwnProperty(tagName)) {return imageSize[tagName];
                } else {return [660, 440];
                }
            }
            let imageModule = new ImageModule(opts);
            // 创建一个 PizZip 实例,内容为模板的内容
            const zip = new PizZip(content);
            // 创建并加载 docxtemplater 实例对象
            const doc = new docxtemplater();
            doc.attachModule(imageModule);
            doc.loadZip(zip);

            doc.setData(wordData);

            try {
                // 用模板变量的值替换所有模板变量
                doc.render();} catch (error) {
                // 抛出异常
                const e = {
                    message: error.message,
                    name: error.name,
                    stack: error.stack,
                    properties: error.properties
                };
                console.log(
                    JSON.stringify({error: e})
                );
                throw error;
            }
            console.log('11');
            // 生成一个代表 docxtemplater 对象的 zip 文件(不是一个真实的文件,而是在内存中的表示)const out = doc.getZip().generate({
                type: 'blob',
                mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
            });
            // 将目标文件对象保存为目标类型的文件,并命名
            saveAs(out, fileName);
        }
    );
};

 

3、参数说明

  • tempDocxPath 是模板文件绝对路径
  • wordData 模板数据
  • fileName 要保存的文件名
  • imageSize 图片大小,接受一个 int 对象,格式是 {width, height},单位是 px,例如 {400, 300}

如需导出图片,则需要将图片转为 base64 后写入 wordData 对象内。

echarts 转 base64 的方法是

echarts.getInstanceByDom(document.getElementById('echarts')).getDataURL({
    type: 'png',
    backgroundColor: '#fff',
    pixelRatio: 1,
})

 

4、模板变量

模板内变量要和 wordData 里的变量名一致。普通字段:{字段名},图片字段:{% 字段名}

 

以上

正文完
 
紫旭
版权声明:本站原创文章,由 紫旭 2023-03-27发表,共计3324字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)