文章目录
一、docxtemplater
用途:使用 Javascript 从应用程序内部生成 docx、pptx 或 xlsx
注意:安装3.5版本即可。不用安装最新版本(官方声明:open-docxtemplater-image-module版本在docxtemplater3.5.2之前是兼容的),可能存在docx无法替换图片 Cannot read properties of undefined (reading ‘part’)的问题。
1.引入相关的库
搭配pizzip(或jszip)、open-docxtemplater-image-module使用
-
pizzip:一个同步压缩文件的库,是JsZip的一个分支
-
open-docxtemplater-image-module:开源 docxtemplater 图片模块
// 引入相关的库
const PizZip = require('pizzip')
const Docxtemplater = require('docxtemplater')
const ImageModule = require('open-docxtemplater-image-module') // 读取模板文件
2.替换数据格式
//文本替换模板
{name1}--------------obj.name1
{name2}--------------obj.name2
//图片替换模板
{%image}--------------obj.image
3.根据模板填充word文档
/**
* 填充word文档
* @param {string} inputPath 模板文件
* @param {{}} data 替换数据
* @param {string} outPutPath 输出文件
*/
fileHelper.replaceWord = async function (inputPath, data, outPutPath) {
try {
console.log(inputPath, outPutPath)
// 读取文件,以二进制文件形式保存
const content = fs.readFileSync(inputPath, 'binary', function () {})
// 压缩数据
const zip = new PizZip(content)
// 生成模板文档
const doc = new Docxtemplater()
const opts = {
centered: false,
getImage: function (tagValue, tagName) {
return fs.readFileSync(
path.join(__dirname, '../template/图片/' + tagValue)
)
},
getSize: function (img, tagValue, tagName) {
return [250, 200]
}
}
doc
.attachModule(new ImageModule(opts))
.loadZip(zip)
.setData(data)
// 渲染数据生成文档
doc.render()
// 将文档转换文nodejs能使用的buf
const buf = doc.getZip().generate({ type: 'nodebuffer' })
// 输出文件
await fs.writeFile(outPutPath, buf, function () {})
} catch (error) {
console.log(error)
}
}
二、officegen
用途:为 Microsoft Office 2007 及更高版本创建 Office Open XML 文件(Word、Excel 和 Powerpoint),无需外部工具,只需纯 Javascript。 officegen应该适用于任何支持 Node.js 的环境,包括 Linux、OSX 和 Windows。 officegen还支持带有嵌入数据的PowerPoint原生图表对象。
1.引入相关的库
const officegen = require('officegen')
2.生成word
async function generateWord (date, inputPath, outputPath) {
const docx = officegen('docx')
// 1.添加文本
const title1 = docx.createP({ align: 'center' })
title1.addText('文本一', { blod: true, font_face: '宋体', font_size: 12 })
title1.addLineBreak() // 换行
title1.addText('文本二')
// 2.添加表格
let pObjTable = docx.createP()
const table = [
['col1', 'col2', 'col3'],
[1, 'All grown-ups were once children', '']
]
const tableStyle = {
tableColWidth: 3261,
tableSize: 24,
tableAlign: 'center',
tableVAlign: 'center',
borders: true, // default is false. if true, default border size is 4
borderSize: 2, // To use this option, the 'borders' must set as true, default is 4
columns: [{ width: 1261 }, { width: 1000 }, { width: 1000 }] // Table logical columns
}
pObjTable = docx.createTable(table, tableStyle)
// 3.添加图片
const pObjPic = docx.createP()
pObjPic.addImage('image.png')
// 获取文件名
const fileName = 'result.docx'
// 导出word
const out = fs.createWriteStream(path.resolve(outputPath, fileName))
// 文件写入
out.on('error', function (err) {
// console.log(err)
return err
})
const result = docx.generate(out) // 服务端生成word
docx.on('finalize', function (written) {
// console.log(
// 'Finish to create Word file.\nTotal bytes created: ' + written + '\n'
// )
return result
})
return result
}
3.自定义样式
3.1 重写水平线
else if (objs_list[i].data[j].horizontal_line) {
console.log(objs_list[i].data[j])
var height =
typeof objs_list[i].data[j].options.height == 'string'
? objs_list[i].data[j].options.height
: '.75'
var fillcolor =
typeof objs_list[i].data[j].options.fillcolor == 'string'
? objs_list[i].data[j].options.fillcolor
: 'e0e0e0'
//outString += `<w:r><w:pict><v:rect o:spt="1" style="width:0;height:${height}pt" o:hralign="center" o:hrstd="t" o:hr="t" fillcolor="#${fillcolor}" stroked="f"></v:rect></w:pict></w:r>`;
outString += `<w:r><w:pict><v:rect o:spt="1" style="height:${height}pt;width:0pt;" fillcolor="#${fillcolor}" filled="t" stroked="f" coordsize="21600,21600" o:hr="t" o:hrstd="t" o:hrnoshade="t" o:hralign="center"></v:rect></w:pict></w:r>`
// Bookmark start support:
}
/**
* Insert a horizontal line inside this paragraph.
*/
MakeDocxP.prototype.addHorizontalLine = function (opt) {
var newP = this
// newP.data[newP.data.length] = { horizontal_line: true }
newP.data[newP.data.length] = { horizontal_line: true, options: opt || {} }
}
使用:
// 4.添加水平线
const pObj = docx.createP()
pObj.addHorizontalLine({
height: '2',
fillcolor: 'FF0000'
})
三、adm-zip
用途:
- 将 zip 文件直接解压缩到磁盘或内存缓冲区中
- 压缩文件并将它们以 .zip 格式或压缩缓冲区存储到磁盘
- 从现有 .zip 更新/添加新/删除文件的内容
说明:可以将word当作zip文件进行解压缩,编辑其中内容
注意:无法解析doc文件,只能解析docx文件。
(docx格式与doc格式都是word文本格式,但是二者的差距实际上是很大的,docx和doc的区别显著的一点就是体积大小的不同。docx格式就是一个zip文件,我们可以拿winrar打开docx文件,得到一堆的文件,很类似android程序或者win7桌面窗体的源码,你在里面可以找到各种配置文件,文本文件和媒体文件。)
1.引入相关的库
const AdmZip = require('adm-zip')
2.解压缩(解析word为原始数据)
const zip = new AdmZip('../test.docx')
// 将该docx解压到指定文件夹temp下,word/document.xml为word文件数据
zip.extractAllTo('../temp', /* overwrite */ true)
3.根据模板填充文件数据(word/document.xml)
const result = await fs.promises.readFile(fileName)
let str = result.toString()
//正则表达式替换数据
const data=[{sourceRegx:/\$\{CE_day\}/g,targetStr:'test'}]
data.forEach(item => {
str = str.replace(item.sourceRegx, item.targetStr)
})
await fs.promises.writeFile(fileName, str.toString())
4.压缩(导出word)
try {
const zip = new AdmZip()
zip.addLocalFolder(inputPath)//inputPath:word文件夹路径
await zip.writeZip(outputPath)//result.docx
} catch (error) {
console.log('生成word,err:', error)
}