1.安装插件
npm install docxtemplater pizzip jszip-utils file-saver docxtemplater-image-module-free
2.util文件夹下创建doc.js文件
import docxtemplater from 'docxtemplater'
import PizZip from 'pizzip'
import JSZipUtils from 'jszip-utils'
import { saveAs } from 'file-saver'
import ImageModule from "docxtemplater-image-module-free";
/**
导出docx
@param { String } tempDocxPath 模板文件路径
@param { Object } data 文件中传入的数据
@param { String } fileName 导出文件名称
*/
export const exportDocx = (tempDocxPath, data, fileName) => {
// 读取并获得模板文件的二进制内容
JSZipUtils.getBinaryContent(tempDocxPath, (error, content) => {
// input.docx是模板。我们在导出的时候,会根据此模板来导出对应的数据
// 抛出异常
if (error) {
throw error
}
let opts = {};
opts.centered = false;
opts.getImage = function (tagValue) {
return new Promise(function (resolve, reject) {
JSZipUtils.getBinaryContent(tagValue, function (error, content) {
if (error) {
return reject(error);
}
return resolve(content);
});
});
};
//图片有关代码,没有图片的可以删除
opts.getSize = (img, tagValue, tagName) => {
return [200, 105]; //图片大小 (固定的)
// 非固定(这里是设置宽度最大为300px的图片)
// return new Promise(function (resolve, reject) {
// let image = new Image();
// image.src = tagValue;
// let imgWidth, imgHeight, scale;
// image.onload = function () {
// imgWidth = image.width;
// imgHeight = image.height;
// scale = 0;
// if (imgWidth > 300) {
// scale = 300 / imgWidth;
// imgWidth = 300;
// imgHeight = imgHeight * scale;
// }
// resolve([imgWidth, imgHeight]);
// };
// image.onerror = function (e) {
// console.log("img, tagValue, tagName : ", img, tagValue, tagName);
// reject(e);
// };
// });
};
let imageModule = new ImageModule(opts);
// 创建一个JSZip实例,内容为模板的内容
const zip = new PizZip(content)
// 创建并加载docxtemplater实例对象
const doc = new docxtemplater().loadZip(zip).attachModule(imageModule).compile();
doc.resolveData({ ...data.form }).then(() => {
doc.render()
const out = doc.getZip().generate({
type: 'blob',
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
}) // Output the document using Data-URI
saveAs(out, fileName)
}).catch(err => console.log('errorsss', err))
})
}
3.在public文件夹里创建.docx文档,示例:
word表格里面写的编码的含义:
- {xxx} 直接渲染数据的xxx字段
- {#xxx}{/xxx} 循环数组数据
- {%xxx} 渲染图片
4.页面使用
import { exportDocx } from '@/util/doc.js'
exportWord(){
const data = {
form: {
title: "工作日报",
officeName: '集团',
options: [
{index:1, name:'测试数据1', number: 1, remark:'这是一条备注信息'},
{index:2, name:'测试数据2', number: 10, remark:'这是一条备注信息'},
], //存放表格数据
filler: '阿强',
filledTime: '2024-04-24',
imgList: [{
img: 'https://images.pexels.com/photos/3291250/pexels-photo-3291250.jpeg?auto=compress&cs=tinysrgb&w=1600&lazy=load'
},{
img: 'https://images.pexels.com/photos/3291250/pexels-photo-3291250.jpeg?auto=compress&cs=tinysrgb&w=1600&lazy=load'
}] //图片数据
}
}
exportDocx('/template.docx', data, `${data.form.title}.docx`)
},
成果:
- .docx文件一定要自己创建,不要找其他模板改,会报错
- 线上的图片路径不存在时,会无法导出,解决方法如下:
- public文件夹下static文件夹放入‘图片不存在’的png图片,线上图片不存在就加载‘图片不存在的图片’
- 判断线上图片是否存在的方法:
-
const checkImgExists = (imgurl) => { return new Promise(function (resolve, reject) { var ImgObj = new Image(); ImgObj.src = imgurl; ImgObj.onload = function () { resolve(imgurl); }; ImgObj.onerror = function (err) { reject("/static/img/failImg.png"); }; }); } //imageList,后端返回的数组图片数据 imageList.map(async (item) => { const res = await this.checkImgExists(item); return { img: res, }; }); Promise.all(newImgList).then((res) => { data.imgList = res })