前端使用docxtemplater导出word文档

2,297 阅读4分钟

word.png 近在做业务系统时,遇到到一个需求。需要系统导出word文档,内容是比较复杂的表格。因为是设计医院系统的打印报告单,这里就不给大家上截图了,搞的挺不好意思的,哈哈哈哈。

image.png

1 docxtemplater 简介

docxtemplater 使用 JSON 数据格式作为输入,可以处理docx 和 ppt模板。不像一些其它的工具,比如 docx.js, docx4j, python-docx 等,需要自己编写代码来生成文件,docxtemplater只需要用户通过标签的形式编写模板,就可以生成文件。有自己的模版语法格式(感兴趣的小伙伴可以多学学)

2 使用教程

2.1 安装依赖

项目所需依赖:docxtemplaterjszipjszip-utilspizzipfile-saver

1、docxtemplater:这个插件可以通过预先写好的word,excel等文件模板生成对应带数据的文件

2、pizzip:这个插件用来创建,读取或编辑.zip的文件(同步的,还有一个插件是jszip,异步的)

3、jszip-utils:与jszip/pizzip一起使用,jszip-utils 提供一个getBinaryContent(path, data)接口,path即是文件的路径,支持AJAX get请求,data为读取的文件内容。

4、file-saver:适合在客户端生成文件的工具,它提供的接口saveAs(blob, "1.docx")将会使用到,方便我们保存文件。

5、docxtemplater-image-module-free:需要导出图片的话需要这个插件

npm 安装如下:

npm install  docxtemplater pizzip --save  // 处理docx模板
npm install  jszip-utils --save
npm install  jszip --save   
npm install  file-saver --save  // 处理输出文件

2.2 创建word模板文件

  • 创建word模板:public/test.docx

vue cli3/vue cli4 在 public 文件下存放word模板test.docx;
vue cli2 在static文件下存放word模板test.docx;

image.png

如果直接在代码编辑器内通过新建文件的方式创建test.docx后面会报错,应该和文件编码格式有关,所以需要进入项目文件夹内右键新建docx文件,test.docx内编辑后编辑器内可以看到pulic文件下多了一个~$test.docx文件;出现这个文件夹基本就可以了。

2.3 docxtemplater 语法

{%img} 图片

{#list}{/list} 循环、if判断

{#list}{/list}{^list}{/list} if else

{str} 文字

docxtemplater 通过标签的形式来填充数据的,简单的数据我们可以使用{} + 变量名来实现简单的文本替换。

2.4 docxtemplater 完整代码实现

创建一个exportWordDocx.js文件,定义一个exportWordDocx函数,接收三个入参,demoUrl代表导出的word文档模板路径,docxData代表模板文档里定义的deptapplyDate 等字段整合给docxData传入即可。fileName代表导出的文件名,方面重命名等操作。

demoUrl传入给JSZipUtils.getBinaryContent方法读取模板文件的二进制内容,之后创建一个PizZip实例,内容为模板的内容,再创建并加载docxtemplater实例对象。

使用doc.setData方法设置模板变量的值,对象的键需要和模板上的变量名一致,值就是你要放在模板上的值。

这里有一个地方需要注意的是:如果你的定义放在模板上的值为null或者undefined,最后导出来的word文档里,相对应的地方会直接显示undefined。解决方法:doc.setOptions 方法里的nullGetter值返回设置为空即可。

最后,通过saveAs方法导出Word文档。

import JSZipUtils from "jszip-utils";
import docxtemplater from "docxtemplater";
import { saveAs } from "file-saver";
import PizZip from "pizzip";

export const exportWordDocx = (demoUrl, docxData, fileName) => {
    // 读取并获得模板文件的二进制内容
    JSZipUtils.getBinaryContent(
        demoUrl,
        function (error, content) {
            // 抛出异常
            if (error) {
                throw error;
            }

            // 创建一个PizZip实例,内容为模板的内容
            let zip = new PizZip(content);
            // 创建并加载docxtemplater实例对象
            let doc = new docxtemplater().loadZip(zip);
            // 去除未定义值所显示的undefined
            doc.setOptions({
                nullGetter: function () {
                    return "";
                }
            }); // 设置角度解析器
            // 设置模板变量的值,对象的键需要和模板上的变量名一致,值就是你要放在模板上的值

            doc.setData({
                ...docxData,
            });

            try {
                // 用模板变量的值替换所有模板变量
                doc.render();
            } catch (error) {
                // 抛出异常
                let e = {
                    message: error.message,
                    name: error.name,
                    stack: error.stack,
                    properties: error.properties,
                };
                console.log(JSON.stringify({ error: e }));
                throw error;
            }

            // 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
            let out = doc.getZip().generate({
                type: "blob",
                mimeType:
                    "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
            });
            // 将目标文件对象保存为目标类型的文件,并命名
            saveAs(out, fileName);
        }
    );
}