前言:
1、前端使用的是vue、element-ui 框架
2、el-table 多选列表,批量勾选数据后,需要每一条数据生成一个word文件,最终导出一个zip压缩包
一、插件准备:
npm install --save docxtemplater pizzip jszip-utils jszip file-saver
如果想使用高级语法,可引入以下两个插件, 可解析更多表达式:
npm install --save angular-expressions lodash
二、创建一个 download-zip.ts 文件,内容为:
import docxtemplater from 'docxtemplater';
import PizZip from 'pizzip';
import JSZipUtils from 'jszip-utils'
import { saveAs } from 'file-saver';
import JSZip from 'jszip';
// 引入angular-expression 解析器
let expressions = require("angular-expressions");
let assign = require("lodash/assign");
expressions.filters.lower = function (input: any) {
if (!input) return input;
return input.toLowerCase();
};
function angularParser(tag: any) {
tag = tag
.replace(/^\.$/, "this")
.replace(/(’|‘)/g, "'")
.replace(/(“|”)/g, '"');
const expr = expressions.compile(tag);
return {
get: function (scope: any, context: any) {
let obj = {};
const scopeList = context.scopeList;
const num = context.num;
for (let i = 0, len = num + 1; i < len; i++) {
obj = assign(obj, scopeList[i]);
}
return expr(scope, obj);
},
};
}
// 导出方法
export const exportDocx = (tempDocxPath: string, list: any[], zipName: string) => {
const promises: any[] = [];
const zips = new JSZip();
// 循环数据,生成word文件
list.forEach((element, index) => {
let fileName = zipName + '(' + index + ')' + '.docx'; // word文件名称
let data = element;
const promise = new Promise((resolver: any, reject) => {
JSZipUtils.getBinaryContent(tempDocxPath, (error: any, content: any) => {
if (error) {
throw error;
}
let zip = new PizZip(content);
let doc = new docxtemplater().loadZip(zip).setOptions({ parser: angularParser });
doc.setData(data);
try {
doc.render();
} catch (error: any) {
throw error;
}
let out = doc.getZip().generate({
type: 'blob',
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
});
// 添至zip集合中
zips.file(fileName, out, { binary: true });
resolver();
})
})
promises.push(promise);
})
// 下载zip包
Promise.all(promises).then(() => {
zips.generateAsync({ type: 'blob' }).then((content: any) => {
saveAs(content, zipName);
})
})
}
三、页面使用:
import { exportDocx } from '@/utils/download-zip';
/**
* @description: 导出成绩单
*/
private exportPoliceInfoFn() {
// 模拟数据
const tempData = [
{
person: {
number: '001',
name: '张三',
age: 20,
sex: 0
},
results: [
{
subject: '语文',
record: 95,
teacher: '李白'
},
{
subject: '数学',
record: 130,
teacher: '华罗庚'
},
{
subject: '物理',
record: 120,
teacher: '钱学森'
}
]
},
{
person: {
number: '002',
name: '李四',
age: 22,
sex: 1
},
results: [
{
subject: '语文',
record: 115,
teacher: '李白'
},
{
subject: '数学',
record: 140,
teacher: '华罗庚'
},
{
subject: '物理',
record: 130,
teacher: '钱学森'
}
]
}
];
// 调用方法
exportDocx('/doc/成绩单.docx', tempData, '成绩单');
}
四、word模板:
五、结果如下:
六、基本语法:
对象:
eg: let person = {name: '张三', age: 34};
{person.name} {person.age} 或者 {#person} {name} {age} {/person}
数组循环:
eg: let list = [{name: '张三', age: 12}, {name: '李四', age: 23}];
{#list}
{name} {age}
{/list}
一维数组循环:
eg: let array = ['one', 'two', 'three'];
{#array}
{.}
{/array}
判断:
{#isTrue}
...
{/}
(完)