【Docx文档操作(三)】基于docxtemplater模板生成文档

一、概述

docxtemplater 插件是将文档模板结合数据生成真正文档的强大工具,对于仅数据发生变化而文档格式固定的文档生成需求,该工具非常好用。
其强大体现在以下三点:

  • 生成的文档会继承模板的字体样式。模板是什么样,生成出来的文档就是什么样,拿来即用。因为其所作的不过是把数据插入模板所在位置
  • 支持常用的模板语法。比如条件判断、数组遍历
  • 支持自定义过滤器。过滤器会在数据插入模板前执行,便于我们对数据进行二次处理,比如复杂或者 需复用的计算逻辑和判断逻辑等,都可以单独创建一个过滤器以我们更熟悉的js语法处理,同时过滤器还支持链式调用

二、如何使用docxtemplater

以下是官方文档的demo,我将结合demo逐步分析docxtemplater所做的事情。
在这里插入图片描述

1、使用docxtemplater的两个前提是docx模板文件和json数据(这里强调必须是docx,也就是doc不行,具体原因第二步会解释)。

在这里插入图片描述

2、利用PizZip包对将模板文件转换为zip包。参考DOCX文档结构分析可知docx与zip是可以相互转换的,但doc则不行,既然无法转化为zip包,自然后续模板解析和文档生成也无法实现。在这里插入图片描述

3、利用docxtemplater处理docx模板文件的zip包。其核心操作就是解压zip包并找到document.xml文件,然后找出其中所有的模板占位符,为后续数据插入做准备。

在这里插入图片描述

4、执行doc.render,顾名思义就是执行渲染操作,这里所做的就是用数据替换模板占位符。(该处理操作类似vue的template,react的jsx渲染数据所做的事情)。在这里插入图片描述

5、以上操作都是对docx文件内部的xml文件进行的,不清楚可以参考前几个博客内容【基于docx-merger实现内容合并基于docx实现文档生成】,这里不再累述。了解之后,对下面步骤做的事情就很清楚了。将第2、3步里对docx的zip包解压得到的文件夹再度压缩得到新的zip包,该zip包所包含的就是新鲜出炉的结合模板和数据的文档。在这里插入图片描述

6、最后将生成的文档数据写入docx文件中。在这里插入图片描述

三、详细介绍

1、数据源

结构:{ data: {} }
定义:data 中是键值对的数据(因为模板中会使用的字段都在 data 对象内,所以都是 data.xxx 格式)

2、模板写法

以下模板写法的功能需结合 angular-parser 词法解析器使用才能发挥功效,未使用 angular-parser 或者使用自定义的词法解析器会存在效果不一致的问题。

2.1、普通变量

{codeName}

默认的模板标识符是花括号(花括号的内容会被视为模板进行解析并从数据源取值),也可以自定义,规则如下:在这里插入图片描述

  • 基础语法支持基本的算术运算符(+、-、*、/)、关系运算符(>、<、>=、<=)、逻辑运算符(&&、||、!);
  • 支持==(类型隐式转换),===(三个等号的类型匹配);
  • 支持布尔值;
  • 支持三元运算式;
  • 支持数组的 length 等属性,但不支持 indexOf/includes 等方法;
    示例:
    在这里插入图片描述
    注意:数据都在 data 下,因此字段代码都需要以 data. 开头;配置空值处理函数后,字段值为 undefined/null,或者字段代码没有匹配到数据,都会显示空。

2.2、判断条件

{#codeName}内容{/}

注意:满足条件才会显示内容,不满足条件则不会显示内容。

2.3、循环遍历

{#codeName}{$index}{col1}{col2}{col3}{/}

循环遍历与判断条件的模板写法相同。此外官方文档给出的示例是以 {#字符代码} 开头,以 {/字符代码} 结尾的,但经过实际测试, {/}也是行得通的,个人觉得更简单。

2.3.1、表格数据遍历

循环遍历不光能针对具体数组值,也可以用于表格增行。
示例:
在这里插入图片描述
注意:表格中每列的值不需要再加前缀,只需填入每列的字段代码;可以通过 $index 获取数组索引,默认从0开始;

2.3.2、字符串数组数据遍历

因为 {#字符代码}{/} 内部可以直接获取遍历项的属性,比如{a:1,b:true}可以直接取{a}、{b},而不用写作{obj.a},{obj.b}。而对于每一项都是基础类型值时,可用{.}指代。
示例:
在这里插入图片描述

2.4、图片组件

{%codeName}

示例:在这里插入图片描述

3、词法解析器

推荐采用 angular-parser 处理词法解析,angular-parser 处理词法解析具有如下优势:

  • 其支持的模板语法规则为花括号包裹内容,如:{user.name}。
  • 增强判断条件和运算能力,支持如下:
    在这里插入图片描述
  • 支持自定义过滤器。
    在这里插入图片描述

4、空值处理函数

为了处理当数据源中无值情况,会增加空值处理函数处理undefined和null,也可以自定义处理其他特殊值的显示问题,以下是默认空值处理函数(当值为undefined或null时显示空字符串,在生成的文档中会什么都不显示)。在这里插入图片描述

5、过滤器

{xxx|filter1|filter2|...}

过滤器能接受参数(在过滤器名称后以 : 分隔),能链式调用(多个过滤器之间以 | 分隔)。
示例:在这里插入图片描述

四、问题处理

1、docxtemplater 支持过滤器接受对象字符串

由于 docxtemplater 模板解析默认通过{}进行变量取值,因此当过滤器中存在对象字符串时,词法解析会识别到连续两个{{的情况,导致语法错误出现。
分析
docxtemplater在对docx文档进行解析并插入数据时,首先会进行词法解析(利用到了分割符和indexOf方法。fullText是docx文档内容字符串,delimiters是取值符。通过getAllIndexes方法分析,词法分析是从左往右依次处理,因此如果存在分割符相互包含的情况就导致词法解析出错)。
在这里插入图片描述
解决方法
通过修改 getAllIndexes 方法源码,令词法解析时能够忽略模板字符串内的分割符,使其能正确进行词法分析(通过在过滤器的对象参数前后用``进行包裹,标识其内部内容为参数,在词法解析时忽略其内部存在的所有分割符)。在这里插入图片描述
但``符号在后续对变量解析的过程中会报编译错误(暂还未查明原因),因此需要在自定义的angularParser编译方法中将`符号转换为’(由于angularParser方法的调用发生在词法分析之后,因此此时将`转化为’没有问题)。在这里插入图片描述

2、docxtemplater 支持图片渲染

docxtemplater官网提供 docxtemplater-image-module 插件实现图片处理,但高版本是收费的,我采用的是免费的低版本,因此存在一些bug得自己处理了(注意:该说法仅做参考,本文档只记录我当时遇到的问题,若官方开放了更高版本,该问题可能就不存在了)。
安装:yarn add docxtemplater-image-module
引入:import ImageModule from ‘docxtemplater-image-module’;
集成
在这里插入图片描述
模板:{%data.image}

3、解析模板语言后渲染图片报错的问题

由于采用的是免费的低版本的 docxtemplater-image-module,发现其在渲染图片时存在bug,通过查看源码定位了问题并找到解决办法。
分析
由于如下 docxtemplater-image-module 源码中 options.scopeManager.getValue(part.value) 未传递 part 作为第二个参数,而 docxtemplater 中处理第二个参数,因而找不到 part 导致的报错。
在这里插入图片描述正常的调用 scopeManager.getValue 的逻辑如下:在这里插入图片描述
解决方法
修改 docxtemplater-image-module 源码。
在这里插入图片描述

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
可以使用JavaScript来操作Word模板生成Word文件。一种常见的方法是使用第方库,如`docxtemplater`或`officegen`来处理Word文档生成。 首先,你需要安装所选库的依赖项。以`docxtemplater`为例,可以使用以下命令安装: ``` npm install docxtemplater ``` 然后,你可以使用以下代码示例来操作Word模板生成Word文件: ```javascript const fs = require('fs'); const Docxtemplater = require('docxtemplater'); // 读取Word模板文件 const templateContent = fs.readFileSync('template.docx', 'binary'); // 创建一个新的Docxtemplater实例 const doc = new Docxtemplater(); // 加载模板内容 doc.loadZip(new JSZip(templateContent)); // 设置要替换的变量值 const data = { name: 'John Doe', age: 30, address: '123 Main Street', }; // 将变量值应用于模板 doc.setData(data); // 渲染模板内容 doc.render(); // 生成Word文件 const output = doc.getZip().generate({ type: 'nodebuffer' }); // 将文件保存到磁盘 fs.writeFileSync('output.docx', output); ``` 在上述示例中,我们首先使用`fs`模块读取Word模板文件的内容。然后,我们创建一个`Docxtemplater`实例,并加载模板内容。接下来,我们设置要替换的变量值,并将其应用于模板。最后,我们渲染模板内容,并将生成的Word文件保存到磁盘。 请注意,这只是一个简单的示例,你可以根据自己的需求进行定制和扩展。另外,还可以使用其他类似的库来完成类似的任务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值