1.下载插件
//-- 安装 docxtemplater
npm install docxtemplater pizzip --save
//-- 安装 jszip-utils
npm install jszip-utils --save
//-- 安装 jszip
npm install jszip --save
//-- 安装 FileSaver
npm install file-saver --save
//--安装 docxtemplater-image-module-free
npm install --save docxtemplater-image-module-free
2.引入依赖
import fileSaver from "file-saver";
import docxtemplater from 'docxtemplater';
import PizZip from 'pizzip';
import JSZipUtils from 'jszip-utils';
import ImageModule from 'docxtemplater-image-module-free ';
如果引入docxtemplater-image-module-free 报错,可尝试使用require方法引入。
const ImageModule = require("docxtemplater-image-module-free");
3.组件内容
父组件
<template>
<div id="app">
<div style="width: 100%; height: 100%;">
<echart ref="chart"></echart>
</div>
<button @click="exportWord()">下载word</button>
</div>
</template>
<script>
import fileSaver from "file-saver";
import docxtemplater from 'docxtemplater';
import PizZip from 'pizzip';
import JSZipUtils from 'jszip-utils';
import echart from "./components/infCharts"
export default {
name: 'App',
data() {
return {
//文档数据
wordData: {
projectName: "二氧化碳排放量统计",
type: "xx",
time: "2022-9-29",
company: "非自然局",
list: [
{ value: 548721, name: "南非" },
{ value: 984207, name: "加拿大" },
{ value: 671493, name: "墨西哥" },
],
},
// 导出文件名字
exportFileName: "二氧化碳排放量报表",
// 模版文件名字(文件需放在public目录下,文件格式为docx)
templateFileName: "templateFile",
// 图表option 数组,可多个图表
// chartOptions: {
// type: Array,
// default: [],
// },
}
},
components: {
echart
},
methods: {
// 导出echarts图片,格式转换
base64DataURLToArrayBuffer(dataURL) {
const base64Regex = /^data:image\/(png|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;
},
// 导出文档
exportWord() {
const ImageModule = require("docxtemplater-image-module-free");
const that = this;
// 存放echarts 图表 base64图片数组
const str = [];
// 读取并获得模板文件的二进制内容
// `${that.templateFileName}.docx`,
JSZipUtils.getBinaryContent(
"template.docx",
(error, content) => {
if (error) {
// 抛出异常
throw error;
}
const zip = new PizZip(content); // 创建一个JSZip实例,内容为模板的内容
const doc = new docxtemplater();
doc.loadZip(zip); // 创建并加载docxtemplater实例对象
// 如果有echarts图表
if (true) {
// for (const iterator of that.$refs["chart"]) {
// // 这个getChartImg方法是我的echart组件中获取echarts图表图片的base64的dataurl
// iterator.getChartImg((chartImg) => {
// str.push({ image: chartImg });
// });
// }
str.push({ image: that.$refs["chart"].getChartImg() });
// 图片处理
const opts = {};
opts.centered = true; // 图片居中,在word模板中定义方式为{%%image}
opts.fileType = "docx";
opts.getImage = (chartId) => {
return that.base64DataURLToArrayBuffer(chartId);
};
opts.getSize = () => {
return [600, 300];
};
const imageModule = new ImageModule(opts);
doc.attachModule(imageModule);
}
doc.setData({ ...that.wordData, chartList: str }); // 设置模板变量的值
try {
doc.render(); // 用模板变量的值替换所有模板变量
} catch (error) {
const e = {
message: error.message,
name: error.name,
stack: error.stack,
properties: error.properties,
};
console.log(JSON.stringify({ error: e }));
throw error; // 抛出异常
}
// 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
const out = doc.getZip().generate({
type: "blob",
mimeType:
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
});
// 将目标文件对象保存为目标类型的文件,并命名
fileSaver.saveAs(out, `${that.exportFileName}.docx`);
}
);
},
}
}
</script>
<style>
#app {
height: 1000px;
background-color: #fff;
text-align: center;
}
button {
background-color: aqua;
}
</style>
图表组件
<template>
<div class="orderEcharts">
<div id="myChart6" :style="{ width: '100%' }"></div>
</div>
</template>
<script>
import echarts from "echarts";
export default {
name: "InfCharts",
data() {
return {
myChart6: "",
infData: [
{ value: 548721, name: "南非" },
{ value: 984207, name: "加拿大" },
{ value: 671493, name: "墨西哥" },
],
};
},
mounted() {
this.drawLine();
},
methods: {
// 获取图表base64图
getChartImg() {
return this.myChart6.getDataURL({
pixelRatio: 2, // 解决模糊
backgroundColor: '#fff'
});
},
drawLine() {
// 基于准备好的dom,初始化echarts实例
this.myChart6 = echarts.init(document.getElementById("myChart6"));
// 绘制图表
let option = {
title: {
text: "二氧化碳排放图表",
//subtext: "纯属虚构",
left: "center",
textStyle: {
color: 'black',
fontSize: 32,
}
},
tooltip: {
trigger: "item",
},
color: ['Orange', '#4682B4', '#696969',],
series: [
{
name: "访问来源",
type: "pie",
radius: "80%",
center: ['50%', '50%'],//设置饼图位置
data: this.infData,
label: {
normal: {
show: true,
position: 'inside',
formatter: (data) => {
return (data.name + "\n" + data.value + " CO₂");
},
textStyle: {
color: 'black',
fontSize: 38,
}
}
},
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: "rgba(0, 0, 0, 0.5)",
},
},
},
],
};
this.myChart6.setOption(option);
//自适应
window.addEventListener("resize", () => {
this.myChart6.resize();
});
},
},
beforeDestroy() {
this.$bus.$off("inf");
},
};
</script>
<style scoped>
.orderEcharts {
width: 100%;
height: 100%;
margin: 0 auto;
display: flex;
justify-content: center;
color: black !important;
}
</style>