导出word文档
需求
思路
本地模板,文档中固定占位符 代码中对应data 运行代码,生成word文档
依赖
docxtemplater (V3.22.3) 由模板生成文档的库 pizzip (V3.0.6) 使用JavaScript创建读取和编辑文件的库 file-saver(V2.0.5) 保存文件的库 docxtemplater-image-module-free(V1.1.1) 开源docxtemplater图像模块
正文
import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import PizZipUtils from "pizzip/utils/index.js";
import { saveAs } from "file-saver";
import ImageModule from "docxtemplater-image-module-free";
async getBase64(imgUrl, callback) {
const image = new Image();
// 解决跨域问题
image.setAttribute("crossOrigin", "anonymous");
const imageUrl = imgUrl;
image.src = imageUrl;
// image.onload为异步加载
// eslint-disable-next-line no-undef
image.onload = function () {
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext("2d");
context.fillStyle = "#fff";
context.fillRect(0, 0, canvas.width, canvas.height);
// eslint-disable-next-line no-undef
context.drawImage(image, 0, 0, image.width, image.height);
var quality = 0.8;
// 这里的dataurl就是base64类型
// 使用toDataUrl将图片转换成jpeg的格式,不要把图片压缩成png,因为压缩成png后base64的字符串可能比不转换前的长!
const dataurl = canvas.toDataURL("image/jpeg", quality);
callback ? callback(dataurl) : null; //调用回调函数
};
},
base64DataURLToArrayBuffer(dataURL) {
const base64Regex = /^data:image\/(png|jpeg|jpg|svg|svg\+xml);base64,/;
if (!base64Regex.test(dataURL)) {
return false;
}
const stringBase64 = dataURL.replace(base64Regex, "");
let binaryString;
if (typeof window !== "undefined") {
binaryString = window.atob(stringBase64);
} else {
binaryString = new Buffer(stringBase64, "base64").toString("binary");
}
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
const ascii = binaryString.charCodeAt(i);
bytes[i] = ascii;
}
return bytes.buffer;
},
function loadFile(url, callback) {
PizZipUtils.getBinaryContent(url, callback);
}
renderDoc(record) {
loadFile("demo.docx", function (error, content) {
// 抛出异常
if (error) {
throw error;
}
const imageOpts = {
getImage(tag) {
return that.base64DataURLToArrayBuffer(tag);
},
getSize() {
return [100, 160];
},
};
const imageModule = new ImageModule(imageOpts);
// 创建一个JSZip实例,内容为模板的内容
var zip = new PizZip(content);
// 创建并加载docxtemplater实例对象
var doc = new Docxtemplater().loadZip(zip).attachModule(imageModule);
// 设置模板变量的值
doc.setData(this.renderData);
try {
// 用模板变量的值替换所有模板变量
doc.render();
} catch (error) {
// The error thrown here contains additional information when logged with JSON.stringify (it contains a properties object containing all suberrors).
function replaceErrors(key, value) {
if (value instanceof Error) {
return Object.getOwnPropertyNames(value).reduce(function (error, key) {
error[key] = value[key];
return error;
}, {});
}
return value;
}
if (error.properties && error.properties.errors instanceof Array) {
const errorMessages = error.properties.errors
.map(function (error) {
return error.properties.explanation;
})
.join("\n");
console.log("errorMessages", errorMessages);
// errorMessages is a humanly readable message looking like this : 'The tag beginning with "foobar" is unopened'
}
throw error;
}
// 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
var out = doc.getZip().generate({
type: "blob",
// type: "text/plain;charset=utf-8",
mimeType:
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
});
// 将目标文件对象保存为目标类型的文件,并命名
let fileName = `out.docx`;
saveAs(out, fileName);
});
},