文章目录
🔎什么是docxtemplater?
docxtemplater 是一个邮件合并工具,以编程方式使用,处理条件、循环,并可扩展以插入图像、html或表格。
docxtemplater 使用 Javascript 对象(或 JSON)作为数据输入,因此也可以轻松地从其他语言中使用(请参阅docker 版本)。
它处理 docx 和 pptx 文件,并且通过附加模块,它可以处理 xlsx 模板
它的工作方式与模板引擎相同,您给它一个模板+一些数据,它就会输出一个生成的文档。
👻docxtemplater语法👻
普通插值
直接在word文档中使用{}
进行包裹字段即可,如图所示:
for循环
常用于列表中(此处只探讨简单的表格,复杂合并表格日后再做探讨)
参数对照
{
...,
arr:[
{
name: "xxx",
gender: "xxx",
age: "xxx"
},
{
name: "xxx",
gender: "xxx",
age: "xxx"
},
{
name: "xxx",
gender: "xxx",
age: "xxx"
},
],
...
}
word中占位语法
选择
常用于勾选,和循环的语法一样
{#list}{/list} 循环、if判断
{#list}{/list}{^list}{/list} if else
图片(🌰代码)
docxtemplater-image-module-free // 导出图片的话需要这个插件
🌰官方代码
javascript
JSZipUtils.getBinaryContent('examples/image-example.docx', function (error, content) {
if (error) {
console.error(error);
return;
}
var opts = {}
opts.centered = false;
opts.getImage = function (tagValue, tagName) {
return new Promise(function (resolve, reject) {
JSZipUtils.getBinaryContent(tagValue, function (error, content) {
if (error) {
return reject(error);
}
return resolve(content);
});
});
}
opts.getSize = function (img, tagValue, tagName) {
// FOR FIXED SIZE IMAGE :
return [150, 150];
// FOR IMAGE COMING FROM A URL (IF TAGVALUE IS AN ADRESS) :
// To use this feature, you have to be using docxtemplater async
// (if you are calling setData(), you are not using async).
return new Promise(function (resolve, reject) {
var image = new Image();
image.src = url;
image.onload = function () {
resolve([image.width, image.height]);
};
image.onerror = function (e) {
console.log('img, tagValue, tagName : ', img, tagValue, tagName);
alert("An error occured while loading " + tagValue);
reject(e);
}
});
}
var imageModule = new ImageModule(opts);
var zip = new JSZip(content);
var doc = new docxtemplater()
.loadZip(zip)
.attachModule(imageModule)
.compile();
doc.resolveData({
image: 'examples/image.png'
}).then(function () {
console.log('ready');
doc.render();
var out = doc.getZip().generate({
type: "blob",
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
});
saveAs(out, "generated.docx");
})
});
在这里就不做赘述,可以搜一下
👻实现下载👻
我们来实现一种最基础的下载,下载单个文件
安装依赖
cmd
npm install docxtemplater pizzip --save // 处理docx模板
npm install jszip-utils --save
npm install jszip --save
npm install file-saver --save // 处理输出文件
🌰完整代码
javascript
import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import PizZipUtils from "pizzip/utils/index.js";
import { saveAs } from "file-saver";
function loadFile(url, callback) {
PizZipUtils.getBinaryContent(url, callback);
}
/**
* 渲染输出文件
* @param {*} fileUrl 文件所在地址
* @param {*} docxParamsArr doc文档参数数组
* @param {*} outDocName 输出文件名
*/
// eslint-disable-next-line no-unused-vars
export function renderDocs(fileUrl, docxParams, outDocName) {
loadFile(fileUrl, function (
error,
content
) {
if (error) {
throw error;
}
const zip = new PizZip(content);
const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true });
doc.render(docxParams);
const out = doc.getZip().generate({
type: "blob",
mimeType:
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
});
saveAs(out, `${outDocName}output.docx`);
});
}
关键逻辑解释
export function renderDocs(fileUrl, docxParams, outDocName) {...}
:这行代码导出了renderDocs
函数,这意味着它可以被其他模块导入和使用。函数有三个参数:fileUrl
(文件的 URL)、docxParams
(doc 文档的参数)和outDocName
(输出文件名)。loadFile(fileUrl, function (error, content) {...})
:在renderDocs
函数内部,它调用了loadFile
函数,传递了fileUrl
和一个回调函数。loadFile
函数可能是一个异步函数,用于从给定的 URL 加载文件内容。回调函数有两个参数:error
(如果发生错误)和content
(文件的内容)。if (error) {...}
:在回调函数内部,检查是否发生错误。如果error
存在,通过throw error;
抛出错误,阻止函数继续执行。const zip = new PizZip(content);
:如果成功加载文件内容,代码使用PizZip
库创建一个新的PizZip
对象。这个对象代表从 URL 下载的文件的 ZIP 归档,可以通过它来访问归档中的内容。const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true });
:创建一个Docxtemplater
对象,将PizZip
对象和一个配置对象传给它。配置对象设置了paragraphLoop
和linebreaks
为true
,这可能使得Docxtemplater
在渲染过程中处理段落循环和行长换行。doc.render(docxParams);
:用Docxtemplater
对象的render
方法来渲染docxParams
。docxParams
可能是一个包含模板变量的对象,这些变量将被替换为模板中的相应占位符。const out = doc.getZip().generate({...});
:渲染完成后,使用doc.getZip().generate({ type: "blob", mimeType: "..." })
生成包含渲染后文档内容的BLOB。这个BLOB可以被保存为文件。saveAs(out,
${outDocName}output.docx);
:最后,使用saveAs
函数保存生成的文档。文件名由outDocName
和output.docx
组成,outDocName
是函数参数,output.docx
是固定的文件名后缀。
👻实现多文件下载👻
现实应用中难免会同时下载多个文件, 如果循环下载,浏览器会反复确认下载(如果浏览器开始下载提示的话),用户体验不是特别友好,操作也十分繁琐
我们可以把多个文件放入文件夹中,然后整成压缩包,进行下载
下面我们来实现一下(在上面的基础之上)
🌰完整代码
javascript
import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import PizZipUtils from "pizzip/utils/index.js";
import { saveAs } from "file-saver";
function loadFile(url, callback) {
PizZipUtils.getBinaryContent(url, callback);
}
/**
* 渲染输出文件
* @param {*} fileUrl 文件所在地址
* @param {*} docxParamsArr doc文档参数数组
* @param {*} outDocName 输出文件名
*/
// eslint-disable-next-line no-unused-vars
export function renderDocs(fileUrl, docxParams, outDocName) {
loadFile(fileUrl, function (
error,
content
) {
if (error) {
throw error;
}
const zip = new PizZip(content);
const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true });
doc.render(docxParams);
const out = doc.getZip().generate({
type: "blob",
mimeType:
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
});
saveAs(out, `${outDocName}output.docx`);
});
}
关键逻辑解释
这段代码定义了一个名为renderDocs
的函数,用于根据提供的文件URL、docx参数数组和输出文件名来渲染和生成文档文件。具体来说,renderDocs
函数做了以下几件事:
-
检查
docxParamsArr
数组的长度:- 如果数组长度为
1
,则创建一个Docxtemplater
对象,将PizZip
对象和一个配置对象传递给它。配置对象中设置了paragraphLoop
和linebreaks
为true
,然后使用该对象渲染docxParamsArr[0]
(数组中的第一个模板参数)。 - 渲染完成后,它使用
doc.getZip().generate({ type: "blob", mimeType: "... })
生成一个包含渲染后文档内容的BLOB。 - 最后,它使用
saveAs(out,
${outDocName}output.docx);
下载生成的文档,文件名根据提供的outDocName
加上后缀output.docx
。
- 如果数组长度为
-
如果
docxParamsArr
数组的长度不为1
,则创建一个JSZip
对象用于生成一个多文档的ZIP文件:- 对于
docxParamsArr
中的每个项,它创建一个Docxtemplater
对象,将PizZip
对象和一个配置对象传递给它。配置对象中设置了paragraphLoop
和linebreaks
为true
,然后使用该对象渲染相应的模板参数。 - 对于每次渲染,它使用
doc.getZip().generate({ type: "blob", mimeType: "... })
生成一个BLOB,并将其作为文件添加到JSZip
对象中,文件名根据索引值确定。 - 渲染和添加所有文件后,它使用
_zip.generateAsync({ type: "blob" })
生成包含所有文件的ZIP BLOB。 - 最后,它使用
saveAs(content,
${outDocName}.zip);
下载生成的ZIP文件,文件名根据提供的outDocName
加上后缀.zip
。
- 对于
注意
文件名字不要一样,要不然会直接替换,多个文件下载,文件名字要实现唯一性