背景
有个业务要求,需要先进行一定的自动化操作
将提取的信息写到Word里
docxtemplater
集成
pnpm add docxtemplater pizzip fs-extra
如果需要插入图片
pnpm add docxtemplater pizzip fs-extra docxtemplater-image-module-free image-size
渲染
// docUtils.js
// PizZip is required because docx/pptx/xlsx files are all zipped files, and
// the PizZip library allows us to load the file in memory
const PizZip = require("pizzip");
const Docxtemplater = require("docxtemplater");
const fs = require("fs-extra");
const ImageModule = require('docxtemplater-image-module-free');
const sizeOf = require("image-size");
// 替换模板key
/**
* filePath: 文档路径
* renderContent: 文档中的key要替换的内容,例如{ image: "examples/image.png" , aa: "123"}
*/
const replaceTemplateKey = (filePath, renderContent) => {
// Load the docx file as binary content
const content = fs.readFileSync(filePath, "binary")
const opts = {
centered: false,
fileType: "docx",//Or pptx
getImage(tagValue, tagName, meta) {
//tagValue is 'examples/image.png'
//tagName is 'image'
// console.log({ tagValue, tagName, meta });
return fs.readFileSync(tagValue);
},
getSize(img, tagValue, tagName) {
//Pass the function that return image size
//img is the image returned by opts.getImage()
//tagValue is 'examples/image.png'
//tagName is 'image'
//tip: you can use node module 'image-size' here
const sizeObj = sizeOf(img);
// console.log(sizeObj);
const multiple = sizeObj.width / 500
const width = sizeObj.width / multiple
const height = sizeObj.height / multiple
return [width, height];
},
}
const zip = new PizZip(content);
const doc = new Docxtemplater(zip, {
modules: [new ImageModule(opts)],
paragraphLoop: true,
linebreaks: true,
});
// 没给的值直接给空
// doc.setOptions({
// nullGetter: function () {
// return "";
// }
// });
doc.render(renderContent);
const buffer = doc.getZip().generate({
type: "nodebuffer",
// compression: DEFLATE adds a compression step.
// For a 50MB output document, expect 500ms additional CPU time
compression: "DEFLATE",
});
fs.writeFileSync(filePath, buffer);
}
module.exports = {
replaceTemplateKey,
}
doc模板
普通的文字
// 模板.docx
你好,我是{name}
renderContent 为
{
name:"张三"
}
输出
你好,我是张三
图片
// 模板.docx
{%template_pic_basic_info}
renderContent 为
{
template_pic_basic_info:"file://a/v/b/c.png"
}
输入一张图片,这里不截图了
布尔,是否渲染
// 模板.docx
{#show1}
你好,我是{name1}
{/show1}
你好,我是{name2}
renderContent 为
{
show1:true,
name1:"张三",
name2:"李四"
}
输出
你好,我是张三
你好,我是李四
renderContent 为
{
show1:false,
name1:"张三",
name2:"李四"
}
输出
你好,我是李四
循环
有多张图片要展示,不知道具体多少张
// 模板.docx
{#template_pic_account_history_info3}
{%image}
{/template_pic_account_history_info3}
renderContent 为
{
template_pic_account_history_info3:[
{image:"xxx/xxx.png"},
{image:"xxx/xxx.png"},
{image:"xxx/xxx.png"},
{image:"xxx/xxx.png"},
],
}
渲染多张图片
End
基本上就能满足大部分的需求了