我的GitHub
0%

无星的前端之旅(三十)——怎么写word

背景

有个业务要求,需要先进行一定的自动化操作

将提取的信息写到Word里

docxtemplater

docxtemplater-官网

docxtemplater-GitHub

集成

1
pnpm add docxtemplater pizzip fs-extra

如果需要插入图片

1
pnpm add docxtemplater pizzip fs-extra docxtemplater-image-module-free image-size

渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// 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模板

普通的文字

1
2
3
// 模板.docx

你好,我是{name}

renderContent 为

1
2
3
{
name:"张三"
}

输出

1
你好,我是张三

图片

1
2
3
4
// 模板.docx

{%template_pic_basic_info}

renderContent 为

1
2
3
{
template_pic_basic_info:"file://a/v/b/c.png"
}

输入一张图片,这里不截图了

布尔,是否渲染

1
2
3
4
5
// 模板.docx
{#show1}
你好,我是{name1}
{/show1}
你好,我是{name2}

renderContent 为

1
2
3
4
5
{
show1:true,
name1:"张三",
name2:"李四"
}

输出

1
2
你好,我是张三
你好,我是李四

renderContent 为

1
2
3
4
5
{
show1:false,
name1:"张三",
name2:"李四"
}

输出

1
你好,我是李四

循环

有多张图片要展示,不知道具体多少张

1
2
3
4
5
// 模板.docx
{#template_pic_account_history_info3}
{%image}
{/template_pic_account_history_info3}

renderContent 为

1
2
3
4
5
6
7
8
{
template_pic_account_history_info3:[
{image:"xxx/xxx.png"},
{image:"xxx/xxx.png"},
{image:"xxx/xxx.png"},
{image:"xxx/xxx.png"},
],
}

渲染多张图片

End

基本上就能满足大部分的需求了

我是阿星,阿星的阿,阿星的星!