Docxtemplater是一个用于生成和操作Word文档的JavaScript库,它允许开发者在前端动态生成和编辑Word文档,用于动态生成报表等功能。
使用方法
-
安装依赖:首先,你需要安装Docxtemplater及其相关依赖。可以通过npm安装这些库:
pnpm install docxtemplater pizzip jszip-utils file-saver docxtemplater-image-module-free -
引入依赖:在项目中引入必要的模块:
import Docxtemplater from 'docxtemplater'; import PizZip from 'pizzip'; import { saveAs } from 'file-saver'; -
创建模板文档:在public文件下创建.docx模板文档,变量用大括号包裹。{#变量}表示循环 {%变量}可以放置图片
-
模板数据匹配:在页面中创建对象进行字段对应
<template>
<div>
<!-- 下载和打印按钮 -->
<button @click="downloadDocument">
Download Document
</button>
<button v-if="outputDoc" @click="printDocument">Print Document</button>
<!-- 错误提示 -->
<div v-if="errorMessage" style="color: red">
{{ errorMessage }}
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import { saveAs } from "file-saver";
import axios from "axios";
const ImageModule = require("docxtemplater-image-module-free");//处理图片
const errorMessage = ref(""); // 存储错误信息
const outputDoc = ref(null); // 存储生成的文档
const userData = {
name: "John Doe",
email: "john.doe@example.com",
age: 30,
option: [
{
id: 1,
gender: 1,
address: "qqq",
},
{
id: 2,
gender: 2,
address: "www",
},
{
id: 3,
gender: 3,
address: "eee",
},
],
people: [
{
position: "CEO",
signatureUrl:
"http://xxxxxxxxxxx",
},
{
position: "CTO",
signatureUrl:
"http://xxxxxxxxxx",
},
],
};
// 加载本地模板文件
async function loadTemplate(filePath) {
const response = await fetch(filePath);
const arrayBuffer = await response.arrayBuffer();
return new Uint8Array(arrayBuffer);
}
// 下载网络图片并转换为 Base64
async function downloadImageToBase64(url) {
const response = await axios.get(url, { responseType: "arraybuffer" });
const base64 = btoa(
new Uint8Array(response.data).reduce(
(data, byte) => data + String.fromCharCode(byte),
""
)
);
return `data:${response.headers["content-type"]};base64,${base64}`;
}
//图片需要转成ArrayBuffer格式
const base64DataURLToArrayBuffer = (dataURL) => {
const base64Regex = /^data:image\/(png|jpg|jpeg|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;
};
// 渲染并生成 .docx 文件
async function generateDocx() {
// 下载图片并更新数据
for (let employee of userData.people) {
employee.signature = await downloadImageToBase64(employee.signatureUrl);
}
let opts = {};
opts = {
// 图像是否居中
centered: false,
};
opts.getImage = (chartId) => {
// console.log(chartId);//base64数据
// 将base64的数据转为ArrayBuffer
return base64DataURLToArrayBuffer(chartId);
};
opts.getSize = function (img, tagValue, tagName) {
// console.log(img);//ArrayBuffer数据
// console.log(tagValue); //base64数据
// console.log(tagName);//wordData对象的图像属性名
// 自定义指定图像大小或直接返回固定尺寸
return [100, 60];
};
// 加载模板文件
const templateContent = await loadTemplate("/template.docx"); // 假设模板文件在 public 目录
const zip = new PizZip(templateContent);
// 初始化 docxtemplater
const doc = new Docxtemplater();
doc.attachModule(new ImageModule(opts));
doc.loadZip(zip);
doc.setData(userData);
try {
doc.render();
errorMessage.value = ""; // 清空错误信息
} catch (error) {
console.error("渲染错误:", error);
errorMessage.value = "Error rendering template. Please check the template and data.";
return;
}
// 生成 .docx 文件
const generatedDoc = doc.getZip().generate({ type: "blob" });
outputDoc.value = generatedDoc;
// 触发文件下载
saveAs(generatedDoc, "output.docx");
}
// 下载文档
const downloadDocument = () => {
// 调用函数
generateDocx();
};
// 打印文档
const printDocument = () => {
const url = URL.createObjectURL(outputDoc.value);
const printWindow = window.open(url);
printWindow.onload = () => { printWindow.print(); };
};
</script>
输出文档
报错提示
如果有类似报错
将包裹图片字段的大括号复制一遍,不要手打,具体为什么识别不出,还没有找到原因。