动态生成word文件并下载
看了很多帖子,最后还是自己搞定的……没一个靠谱的,都说不清楚,那就自己动手吧!
下载依赖
npm i docxtemplater
npm i file-saver
npm i pizzip
新建docx的word模板
- 建议在项目文件夹里面手动创建,不要在编译器里面创建。
- 要在public目录下创建,和favicon.ico这个图片在同一等级的目录下创建哦。 我这里是命名的demo.docx。
- 在这个docx文件里写上模板,具体应该是{}+内容:
新建ts文件
在哪里创建都行,反正他只扫描public里面的文件,我这里命名的是exportWord.ts文件。
在里面复制粘贴以下代码:
import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import PizZipUtils from "pizzip/utils/index.js";
import {
saveAs
} from "file-saver";
export const exportWordDocx = () => {
// 读取并获得模板文件的二进制内容
function loadFile(url: string, callback: (error: any, content: any) => void) {
PizZipUtils.getBinaryContent(url, callback);
}
// demo.docx是模板。我们在导出的时候,会根据此模板来导出对应的数据
loadFile("demo.docx", function(
error:Error | null,
content
) {
// 抛出异常
if (error) {
throw error;
}
console.log(content)
// 创建一个JSZip实例,内容为模板的内容
const zip: PizZip = new PizZip(content);
const doc: Docxtemplater = new Docxtemplater().loadZip(zip) as Docxtemplater;
// 设置模板变量的值
doc.setData({
title: "John",
});
try {
// 用模板变量的值替换所有模板变量
doc.render();
} catch (error:any) {
// The error thrown here contains additional information when logged with JSON.stringify (it contains a properties object containing all suberrors).
// eslint-disable-next-line no-inner-declarations
function replaceErrors(key:any, value:any) {
if (value instanceof Error) {
return Object.getOwnPropertyNames(value).reduce(function(
error: any,
key: string
) {
error[key] = value[key as keyof Error];
return error;
}, {});
}
return value;
}
console.log(JSON.stringify({
error: error
}, replaceErrors));
if (error.properties && error.properties.errors instanceof Array) {
const errorMessages = error.properties.errors
.map(function(error:any) {
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文件(不是一个真实的文件,而是在内存中的表示)
const out = doc.getZip().generate({
type: "blob",
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
});
// 将目标文件对象保存为目标类型的文件,并命名
saveAs(out, "output.docx");
});
}
里面有这一行:
loadFile("demo.docx", function(
这个是你的模板文件。
还有这样一行:
title: "John",
这是你的数据,要和上面那个docx文件的内容对应的上。
还有最后的一行:
saveAs(out, "output.docx");
这个output.docx是你下载以后的文件名称。
在vue文件中引入
这个就很简单了,直接
import exportWordDocx from ‘你的这个ts文件目录’
exportWordDocx 是你上面ts文件的开头,导出的名称。
然后在button按钮上使用点击事件,直接调用就行了!
<template>
<button @click="exportWord">123123</button>
</template>
<script setup lang="ts">
import {exportWordDocx} from "@/plugins/exportWord";
const exportWord=()=>{
exportWordDocx()
}
</script>
如果你不想要ts,这里也有ts装成的js代码
import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import PizZipUtils from "pizzip/utils/index.js";
import {
saveAs
} from "file-saver";
export const exportWordDocx = () => {
// 读取并获得模板文件的二进制内容
function loadFile(url, callback) {
PizZipUtils.getBinaryContent(url, callback);
}
// demo.docx是模板。我们在导出的时候,会根据此模板来导出对应的数据
loadFile("demo.docx", function(
error,
content
) {
// 抛出异常
if (error) {
throw error;
}
console.log(content)
// 创建一个JSZip实例,内容为模板的内容
var zip = new PizZip(content);
// 创建并加载docxtemplater实例对象
var doc = new Docxtemplater().loadZip(zip);
// 设置模板变量的值
doc.setData({
title: "John",
});
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).
// eslint-disable-next-line no-inner-declarations
function replaceErrors(key, value) {
if (value instanceof Error) {
return Object.getOwnPropertyNames(value).reduce(function(
error,
key
) {
error[key] = value[key];
return error;
}, {});
}
return value;
}
console.log(JSON.stringify({
error: error
}, replaceErrors));
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",
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
});
// 将目标文件对象保存为目标类型的文件,并命名
saveAs(out, "output.docx");
});
}