最近开发中遇到需要列表中的表格数据导出word,由于列表表格中的数据是动态表单拖拽产生的,格式就不太固定,想到的方案就是,固定个word模板,然后拿出表格的模板字段进行赋值导出,具体业务实现就不细说,下面说下导出实现 。
需要的相关插件
docxtemplaterpizzipfile-saverjszip-utilsjszipdocxtemplater-image-module-free
jszip: 是为了生成压缩包批量下载,不需要批量处理的可以不用安装
docxtemplater-image-module-free: 如果导出设计到图片的需要安装没有的也可以不用安装
安装
npm i docxtemplater pizzip jszip-utils file-saver jszip docxtemplater-image-module-free -S
处理逻辑
- 读取并获得模板文件的二进制内容
JSZipUtils.getBinaryContent('test.docx', (error, content) => {})
2.文件转zip 文件
const zip = new PizZip(content);
3.创建并加载docxtemplater实例对象
let doc = new docxtemplater().loadZip(zip).compile();
4.加载数据
5.模板定义
模板
测试数据
测试数据
效果展示
图片关键代码处理
批量下载处理
这个地方在打包完下载的时候加了个延迟处理,避免操作不完全
综合封装下
对上面的分散JS做下封装处理,新建exportWord.jsimport docxtemplater from "docxtemplater"import PizZip from "pizzip"import { saveAs } from "file-saver"import JSZipUtils from "jszip-utils"import JSZip from 'jszip'import ImageModule from "docxtemplater-image-module-free"export const dataURLToBase64 = (url) => {return new Promise((resolve, reject) => {// 判断下传入的地址是不是已经是base64const base64Regex = /^data:image/(png|jpg|svg|svg xml);base64,/;if (base64Regex.test(url)) {return url;}const Img = new Image()let dataURL = ''Img.setAttribute('crossOrigin', 'Anonymous')Img.src = https://www.itzhengshu.com/word/url'?v='Math.random()Img.onload = function () {// 要先确保图片完整获取到,这是个异步事件const canvas = document.createElement('canvas') // 创建canvas元素const width = Img.width // 确保canvas的尺寸和图片一样const height = Img.heightcanvas.width = widthcanvas.height = heightcanvas.getContext('2d').drawImage(Img, 0, 0, width, height) // 将图片绘制到canvas中dataURL = canvas.toDataURL('image/jpeg') // 转换图片为dataURLresolve(dataURL)}})}export const exportWord = ({ file = "input.docx", data, filename = "下载文档", fileType = "docx", folder = "下载文档" } = {}) => {// 批量下载生成压缩包const Zip = new JSZip()if (Array.isArray(data)) {data.map((item, index) => {// 读取并获得模板文件的二进制内容JSZipUtils.getBinaryContent(file, (error, content) => {// input.docx是模板 。我们在导出的时候 , 会根据此模板来导出对应的数据// 抛出异常if (error) {throw error}// 图片处理let opts = {}opts.centered = true;// 图片居中opts.getImage = (tagValue, tagName) => {return new Promise((resolve, reject) => {JSZipUtils.getBinaryContent(tagValue, (error, content) => {if (error) {return reject(error);}return resolve(content);});});}opts.getSize = () => {return [400, 200]}let imageModule = new ImageModule(opts);// 创建一个JSZip实例,内容为模板的内容const zip = new PizZip(content);// 创建并加载docxtemplater实例对象let doc = new docxtemplater().loadZip(zip).attachModule(imageModule).compile();let word = Zip.folder(folder)doc.resolveData(item).then(() => {doc.render();const out = doc.getZip().generate({type: "blob",mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",});word.file(`${item.filename ? item.filename : filenameindex}.${fileType}`, out)})console.log(word, 'word')})})setTimeout(() => {Zip.generateAsync({ type: "blob" })// zip下载.then((content) => {saveAs(content, `${folder}.zip`);// zip下载后的名字});}, 1000)} else {// 读取并获得模板文件的二进制内容JSZipUtils.getBinaryContent(file, (error, content) => {// 抛出异常if (error) {throw error}// 图片处理let opts = {}opts.centered = true;// 图片居中,在word模板中定义方式为{%image}opts.getImage = (tagValue, tagName) => {return new Promise((resolve, reject) => {JSZipUtils.getBinaryContent(tagValue, (error, content) => {if (error) {return reject(error);}return resolve(content);});});}opts.getSize = () => {return [600, 300]}let imageModule = new ImageModule(opts);const zip = new PizZip(content);// 创建并加载docxtemplater实例对象let doc = new docxtemplater().loadZip(zip).attachModule(imageModule).compile();// 如果包含异步数据,用resolveData,在回调之后再处理,如果都是同步数据,直接用setData就可以doc.resolveData(data).then(() => {try {// 用模板变量的值替换所有模板变量doc.render();// 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)const out = doc.getZip().generate({type: "blob",mimeType:"application/vnd.openxmlformats-officedocument.wordprocessingml.document"});// 将目标文件对象保存为目标类型的文件,并命名saveAs(out, `${filename}.${fileType}`);} catch (error) {// 抛出异常const e = {message: error.message,name: error.name,stack: error.stack,properties: error.properties};console.log(JSON.stringify({ error: e }));throw error;}})});}}
使用
导入上面定义的JS,使用exportWord方法import {exportWord} from './exportWord'const config = {file: "test.docx",filename:'下载文档',fileType:'docx',folder:'下载文档',data: {}// 数据}exportWord(config)
参数说明:
类型
默认值
说明
file
String
模板文件的地址
filename
String
下载文档
文件名称
fileType
String
docx
文件类型
folder
String
下载文档
批量下载压缩包的文件名
data
Array/Object
{}
数据(数组默认批量,对象默认单个下载)
【word文档怎么导出模板 模版导出word下载】开发的过程中也看到了别人写的,也借鉴参考学到了很多,这地方再进行整合下希望能帮助到也需要相似功能的你们 。