vuecli4 使用docxtemplater导出word(超详细)
项目需求:前端层面实现导出word功能
项目准备:
- vue脚手架项目(vue-cli4)
- 插件:docxtemplater pizzip jszip jszip-utils file-saver
1.安装依赖:
npm install docxtemplater pizzip --save // 处理docx模板
npm install jszip-utils --save
npm install jszip@2.6.1 --save
npm install file-saver --save // 处理输出文件
- 坑1:执行npm install jszip --save 会下载最新版本导致报错,必须指定版本号,亲测2.6.1版本可行
2.创建word模板:public/test.docx
- vuecli3/vuecli4在public文件下存放word模板test.docx;vuecli2在static文件下存放word模板test.docx;
- word模板示例:
- 坑2:如果直接在代码编辑器内通过新建文件的方式创建test.docx后面会报错,应该和文件编码格式有关,所以需要进入项目文件夹内右键新建docx文件,test.docx内编辑后编辑器内可以看到pulic文件下多了一个~$test.docx文件;出现这个文件夹基本就okay了
3.封装导出word组件:src/components/export2word.vue
<template>
<div>
<div class="word-box" @click="exportWord">word</div>
</div>
</template>
<script>
import Docxtemplater from 'docxtemplater';
import JSZip from 'jszip';
import JSZipUtils from 'jszip-utils';
import { saveAs } from 'file-saver';
export default {
name: 'Docx',
props: {
fileName: {
type: String, // 输出文件名
default: ''
},
fileTemplete: {
type: String, // public下存放的word模板名称
default: ''
},
exportData: {
type: Object, // 导出的word数据
default: () => { }
}
},
methods: {
// 点击导出word
exportWord() {
// 读取并获得模板文件的二进制内容
JSZipUtils.getBinaryContent(this.fileTemplete + '.docx', (error, content) => {
// 抛出异常
if (error) throw error;
// 创建一个JSZip实例,内容为模板的内容
let zip = new JSZip(content);
// 创建并加载docxtemplater实例对象
let doc = new Docxtemplater();
doc.loadZip(zip);
// 设置模板变量的值
doc.setData({
...this.exportData
});
try {
// 用模板变量的值替换所有模板变量
doc.render();
} catch (error) {
// 抛出异常
let e = {
message: error.message,
name: error.name,
stack: error.stack,
properties: error.properties
};
console.log(JSON.stringify({ error: e }));
throw error;
}
// 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
let out = doc.getZip().generate({
type: 'blob',
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
});
// 将目标文件对象保存为目标类型的文件,并命名
saveAs(out, this.fileName + '.docx');
});
},
},
}
</script>
4.页面使用word组件:src/views/page.vue
<template>
<div class="page">
<Download
class="download"
:fileName="fileName"
:fileTemplete="fileTemplete"
:exportData="exportData"
/>
</div>
</template>
<script>
import Download from '@/components/export2word.vue';
export default {
data() {
return {
fileName: '2021年度销售业绩报告',
fileTemplete: 'test',
exportData: {
"code": "value",
"data": {
"dataArr0": {
"key1": "value1",
"key1": "value1",
"key1": "value1",
"key1": "value1",
},
"dataArr1": {
"key1": "value1",
"key1": "value1",
"key1": "value1",
"key1": "value1",
},
"dataArr2": {
"key1": "value1",
"key1": "value1",
"key1": "value1",
"key1": "value1",
},
"dataArr3": {
"obj1": {
"key1": "value1",
"key1": "value1",
"key1": "value1",
"key1": "value1",
},
"obj2": {
"key1": "value1",
"key1": "value1",
"key1": "value1",
"key1": "value1",
},
"obj3": {
"key1": "value1",
"key1": "value1",
"key1": "value1",
"key1": "value1",
},
"key2": "value2",
"key3": "value3",
},
"dataArr4": [
{
"key1": "value1",
"key1": "value1",
"key1": "value1",
"key1": "value1",
},
{
"key1": "value1",
"key1": "value1",
"key1": "value1",
"key1": "value1",
},
{
"key1": "value1",
"key1": "value1",
"key1": "value1",
"key1": "value1",
},
{
"key1": "value1",
"key1": "value1",
"key1": "value1",
"key1": "value1",
},
{
"key1": "value1",
"key1": "value1",
"key1": "value1",
"key1": "value1",
}
],
"dataArr5": {
"key1": "value1",
"key1": "value1",
"key1": "value1",
"key1": "value1",
}
}
},
}
},
components: {
Download,
},
}
</script>
<style>
.page {
box-sizing: border-box;
width: 100%;
height: 100vh;
user-select: none;
}
.page .download {
border: 1px solid #000;
padding: 5px 10px;
height: 50px;
margin-left: 100px;
cursor: pointer;
}
</style>
5.填充word模板数据:
填充数据根据渲染数据的结构而定,这里提供了数组和对象数据结构
解析变量:{变量名} 循环: {#数组名} {元素名1}{元素名2}.... {/数组名} 条件: {#条件} {变量} {/条件}
- 坑3:注意使用JS对象点语法是访问不到变量的,对象格式数据访问{#父对象名}{子属性}{/父对象名}
- 坑4:表格中loop必须在表格内开始 表格内结束
结论
好好啃官网,就是看起来好烦,附上官网供你们继续烦:https://docxtemplater.com/doc...
推荐阅读
windows10 微软商店 Code: 0x80131500
1. 尝试过的方案(noted: 建议都试下) {代码...} 2. 最终解决方案 {代码...} 3. 不得不吐槽 {代码...}
guyu阅读 32
「多图预警」完美实现一个@功能
一天产品大大向 boss 汇报完研发成果和产品业绩产出,若有所思的走出来,劲直向我走过来,嘴角微微上扬。产品大大:boss 对我们的研发成果挺满意的,balabala...(内心 OS:不听,讲重点)产品大大:咱们的客服 I...
wuwhs赞 39阅读 4.7k评论 5
【已结束】SegmentFault 思否写作挑战赛!
SegmentFault 思否写作挑战赛 是思否社区新上线的系列社区活动在 2 月 8 日 正式面向社区所有用户开启;挑战赛中包含多个可供作者选择的热门技术方向,根据挑战难度分为多个等级,快来参与挑战,向更好的自己前进!
SegmentFault思否赞 20阅读 5.5k评论 10
用了那么久的 SVG,你还没有入门吗?
其实在大部分的项目中都有 直接 或 间接 使用到 SVG 和 Canvas,但是在大多数时候我们只是选择 简单了解 或 直接跳过,这有问题吗?没有问题,毕竟砖还是要搬的!
熊的猫赞 16阅读 1.5k评论 2
嘿,vue中keep-alive有个「大坑」你可能还不知道
背景是这样的,我们使用vue2开发一个在线客服使用的IM应用,基本布局是左边是访客列表,右边是访客对话,为了让对话加载更友好,我们将对话的路由使用<keep-alive>缓存起来。但是如果将所有对话都缓存,未...
wuwhs赞 12阅读 2.5k
什么?后端要一次性返回我10万条数据!且看我这8种方案机智应对!
问题描述面试官:后端一次性返回10万条数据给你,你如何处理?我:歪嘴一笑,what the f**k!问题考察点看似无厘头的问题,实际上考查候选人知识的广度和深度,虽然在工作中这种情况很少遇到...考察前端如何处理大...
水冗水孚赞 15阅读 3.6k评论 1
你可能需要的多文档页面交互方案
在日常工作中,面对不同的需求场景,你可能会遇到需要进行多文档页面间交互的实现,例如在 A 页面跳转到 B 页面进行某些操作后,A 页面需要针对该操作做出一定的反馈等等,这个看似简单的功能,却也需要根据不同...
熊的猫赞 8阅读 1.2k
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。