前端如何导出doc文档-docxtemplater
摘要:
为减少服务器压力,统计文档的导出需要前端实现,后端仅返回统计数据。本文将介绍使用docxtemplater导出文档,纯前端浏览器导出。
安装依赖
bash
npm i docxtemplater pizzip docxtemplater-image-module-free file-saver
依赖说明:
- docxtemplater:导出模板文档库
- pizzip:加载资源文件内容、对模版内容进行解压及压缩。
- docxtemplater-image-module-free:对图片处理的模块(没有图片可不安装)。
- file-saver:将文件保存到本地
docxtemplater语法
{str} 文字
{%img} 图片
{#list}{/list} 循环、if判断
{#list}{/list}{^list}{/list} if else
{@rawXml} 原始xml,最强大的功能,如:要对表格列循环、插入任意样式的内容。
模板效果如下:

编写代码
获取模板内容
- 如果模板文件时在远程服务器,通过url获取,使用此方法
ts
import PizZipUtils from 'pizzip/utils/index.js';
/**
* 获取模板文件内容
* @param templateFile 模版地址url
* @returns
*/
function getFileBinaryString(templateFile: string): Promise<ArrayBuffer> {
return new Promise((resolve, reject) => {
PizZipUtils.getBinaryContent(templateFile, (err, content: any) => {
if (err) {
return reject(err);
}
resolve(content as ArrayBuffer);
});
});
}
- 如果文件是本地选择的文件,使用此方法获取
ts
/**
* 获取模板文件内容
* @param blob 模版文件,通过input[type="file"]获取e.target.files[0]
* @returns
*/
function getFileBinaryString(blob: Blob): Promise<ArrayBuffer> {
return new Promise((resolve, reject) => {
const file = new FileReader();
file.onload = () => {
resolve(file.result as ArrayBuffer);
};
file.onerror = reject;
file.readAsArrayBuffer(blob);
});
}
图片导出配置(没有图片可不配置)
ts
import PizZipUtils from 'pizzip/utils/index.js';
const imageOpts = {
// 获取图片内容
getImage: (tagValue, tagName) => {
return new Promise((resolve, reject) => {
PizZipUtils.getBinaryContent(tagValue, (error, content) => {
if (error) {
return reject(error);
}
return resolve(content);
});
});
},
// 获取图片大小
getSize: (img, tagValue, tagName) => {
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => {
resolve([image.width, image.height]);
};
image.onerror = (e) => {
console.log('load image error', img, tagValue, tagName, e);
reject(e);
};
image.src = tagValue;
});
},
};
生成文档
ts
import PizZip from 'pizzip';
import DocxTemplater from 'docxtemplater';
import ImageModule from 'docxtemplater-image-module-free';
/**
* 根据模板生成文档文件
* @param template 模版url
* @param fileData 填充的数据
* @returns
*/
export async function generateDocxFile(template: string, fileData: Record<string, any>) {
// 获取模板内容,根据自己的情况,调用第一步的方法,这里是用远程url的方式获取的
const templateData = await getFileBinaryString(template);
// 使用PizZip处理模板数据
const zip = new PizZip(templateData);
// 初始化模板。没有图片可以不配置 modules
const doc = new DocxTemplater(zip, { modules: [new ImageModule(imageOpts)] });
// 往模板填充数据
await doc.renderAsync(fileData);
// 生成blob数据,用于下载
const out = doc.getZip().generate({
type: 'blob',
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
});
return out;
}
外部调用
ts
import { saveAs } from 'file-saver';
async function handleExportDocx() {
const templateUrl = 'https://xxxxx.oss-cn-beijing.aliyuncs.com/template/xxx.docx';
const out = await generateDocxFile(templateUrl, {
// 字符串
title: '标题',
// 数组
users: [
{ id: 1, name: '张三' },
{ id: 2, name: '李四' },
{ id: 3, name: '王五' },
],
// 图片的远程地址
imgUrl: 'https://xxxxx.oss-cn-beijing.aliyuncs.com/xxx.png',
// 通过echarts生成的图表图片数据、canvas数据
imgDataUrl: echarts.getDataURL(),
// 布尔
isBuy: true
});
saveAs(out, `xxxx.docx`);
}
最终效果

完整代码
ts
import PizZip from 'pizzip';
import DocxTemplater from 'docxtemplater';
import ImageModule from 'docxtemplater-image-module-free';
import PizZipUtils from 'pizzip/utils/index.js';
import { saveAs } from 'file-saver';
const imageOpts = {
getImage: (tagValue, tagName) => {
return new Promise((resolve, reject) => {
PizZipUtils.getBinaryContent(tagValue, (error, content) => {
if (error) {
return reject(error);
}
return resolve(content);
});
});
},
getSize: (img, tagValue, tagName) => {
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => {
resolve([image.width, image.height]);
};
image.onerror = (e) => {
console.log('图片加载失败', img, tagValue, tagName, e);
reject(e);
};
image.src = tagValue;
});
},
};
/**
* 获取模板文件内容
* @param templateFile 模版地址url
* @returns
*/
function getFileBinaryString(templateFile: string): Promise<ArrayBuffer> {
return new Promise((resolve, reject) => {
PizZipUtils.getBinaryContent(templateFile, (err, content: any) => {
if (err) {
reject(err);
return;
}
resolve(content as ArrayBuffer);
});
});
}
/**
* 根据模板生成文档文件
* @param template 模版url
* @param fileData 填充的数据
* @returns
*/
export async function generateDocxFile(template: string, fileData: Record<string, any>) {
const templateData = await getFileBinaryString(template);
const zip = new PizZip(templateData);
const doc = new DocxTemplater(zip, { modules: [new ImageModule(imageOpts)] });
await doc.renderAsync(fileData);
const out = doc.getZip().generate({
type: 'blob',
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
});
return out;
}
// 导出文件
async function handleExportDocx() {
const templateUrl = 'https://xxxxx.oss-cn-beijing.aliyuncs.com/template/xxx.docx';
const out = await generateDocxFile(templateUrl, {
// 字符串
title: '标题',
// 数组
users: [
{ id: 1, name: '张三' },
{ id: 2, name: '李四' },
{ id: 3, name: '王五' },
],
// 图片的远程地址
imgUrl: 'https://xxxxx.oss-cn-beijing.aliyuncs.com/xxx.png',
// 通过echarts生成的图表图片数据、canvas数据
imgDataUrl: echarts.getDataURL(),
// 布尔
isBuy: true
});
saveAs(out, `xxxx.docx`);
}
{@rawXml}
将docx文件保存为xml文件,就可以看的原始xml,可以把自己需要复制出来,修改成自己需要的内容,进行插入。
更多模块

评论
0条评论
暂无内容,去看看其他的吧~