1. 功能需求:
如果业主要求项目支持下载可编辑的导出格式,则会很少见得做word格式导出功能。
2. 工具:
word导出可以用docxtemplater工具。
3. 用法:
① 安装依赖:npm install docxtemplater pizzip --save-dev
(如果有echart图等图片,还需要安装ImageModule依赖 npm install --save docxtemplater-image-module-free
)
② 在需要用到的vue文件中导入依赖
import 'docxtemplater/build/docxtemplater.js'
import 'pizzip/dist/pizzip.js'
import 'pizzip/dist/pizzip-utils.js'
import 'file-saver'
import ImageModule from 'docxtemplater-image-module-free' // 如果模板里有图片需要引入
③ 导出函数:
html:
<el-button class="saveButton" @click="generate">下载</el-button>
js:
export default {
data () {
return {
wordData: {} // 导出word格式文件所用到的数据
}
},
methods () {
// word导出 - 编译
loadFile(url, callback) {
PizZipUtils.getBinaryContent(url, callback);
},
// word导出 - 存储数据
wordSetData () {
this.wordData = {} // word数据初始化
... // 这里把相应页面数据塞进去
},
// word导出 - 生成word文件
generate() {
this.wordSetData()
// 下面这段代码是官网给的代码,除了loadFile的模板文件路径,其他什么都没必要动。只要文件路径对了,就可以成功导出。
// 而如果模板里有图片,则需要多加载一个图片模块
// 不过注意如果模板里的占位符格式写错,也可能报错导出失败
var that = this;
this.loadFile("InspectionWordTemplate.docx", function (error, content) {
if (error) {
throw error
};
// 有图片的话,需加上下面这段代码
// let opts = {}
// opts.centered = false;
// opts.fileType = "docx";
// opts.getImage = function (chartId) {
// return that.base64DataURLToArrayBuffer(chartId);
// }
// opts.getSize = function () {
// return [481, 282]
// }
// let imageModule = new ImageModule(opts);
var zip = new PizZip(content);
let doc = new docxtemplater();
// 有图片的话,需加载图片处理模块
// doc.attachModule(imageModule);
doc.loadZip(zip);
doc.setData({
...that.wordData
});
try {
// render the document (replace all occurences of {first_name} by John, {last_name} by Doe, ...)
doc.render()
} catch (error) {
var e = {
message: error.message,
name: error.name,
stack: error.stack,
properties: error.properties,
}
console.log(JSON.stringify({
error: e
}));
// The error thrown here contains additional information when logged with JSON.stringify (it contains a property object).
throw error;
}
var out = doc.getZip().generate({
type: "blob",
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
}) //Output the document using Data-URI
saveAs(out, '导出文件' + ".docx")
})
},
},
// 导出echarts图片,格式转换(插件生成图片时使用的不是base64格式的图片,需要在这里转换过)
// 模板里没有图片的话不用加下面这个方法
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;
},
}
④ docxtemplater的模板里占位符/标签的用法:
类型 | 格式 | 备注 |
---|---|---|
变量 | {title} | |
图片 | {%url} | 如果模板里要放图片,需给插件额外加载图片模块ImageModule |
循环 | {#list}{name}{/list} | 比如:list数组里放name变量 |
条件 | {#hasName}{name}{/hasName} | hasName为布尔类型,如果为true则显示标签内部包含的内容 |
js运算符条件判断 | {#num && flag}{name}{/} | 以#/包括的标签,可通过条件判断是否显示,上一条也属于这种情况,其他还可以用的有&&`` |
if-else | {#hasName}{name}{/hasName} {^hasName}没有名字{/hasName} | ^符号标签包含的内容为hasName为false时显示的内容 |
换行 | 注意标签的换行也会导致内容的换行 | |
html标签 | {"html": "<h1>docxtemplater</h1>"} | 可以用class、行间样式、样式表等 |
过滤器 | 同html |
⑤ 注意点:
-
如果是vue2项目,必须把docx模板文件放在static目录下
如果是vue3项目,必须把docx模板文件放在public目录下
-
模板文件必须是.docx文件,注意不能用.doc格式
-
注意配置文件里的publicPath:
如果是
publicPath: "./"
,那么文件路径直接写名字this.loadFile("InspectionWordTemplate.docx", function (error, content) {}
;如果是
publicPath: "/"
,那么文件路径要用../../
的格式填入相对路径 -
如果需要插入图片,则需要引入
docxtemplater-image-module
如果需要插入表格,则需要引入docxtemplater-table-module
(插入表格模板教程)
⑥ 常见报错
-
Uncaught Error: Can't find end of central directory : is this a zip file ?
:原因:路径错了,找不到模板文件;或者模板文件格式错了,比如放了.doc格式文件
-
Uncaught TypeError: Cannot set property namespaceURI of #<Element> which has only a getter
原因:如果模板里有图片,需要再安装
image-module
依赖,此时依赖里的js文件可能会报错方法:打开依赖里的
\node_modules\docxtemplater-image-module-free\js\imgManager.js
文件,删除掉所有newTag.namespaceURI = null;
即可
Do what you can, with what you have, where you are.
在你所处的位置,用你所有的资源,做你力所能及的事。(西奥多·罗斯福)