使用docxtemplater模板语法,导出多个word文件,并生成zip压缩包

发布于:2023-04-27 ⋅ 阅读:(175) ⋅ 点赞:(0)

前言:

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}
...
{/}

(完)


网站公告

今日签到

点亮在社区的每一天
去签到