【插件】前端生成word 文件
文章目录
- 1、背景
- 2、方式一:html-docx-js
- 2.1 具体代码
- 2.2 前端生成word文件的样式
- 2.3 总结
- 3、方式二:pizzip + docxtemplater
- 3.1 具体代码
- 3.2 前端生成word文件的样式
- 3.3 总结
- 4、参考链接
1、背景
在实际开发中,业务需要,需要把数据进行组合生成一个 word 文件
2、方式一:html-docx-js
注意
,这个插件 最近的更新日期八年
之前了
2.1 具体代码
核心逻辑
- 画出
Word 文件内容
样子 - 把 word文件内容样子的
DOM
。传入html-docx-js
的asBlob
方法 - 处理
blob
格式的数据,配合a 标签
,直接在界面弹出文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>HTML to Word</title>
<script src="https://cdn.jsdelivr.net/npm/html-docx-js@0.3.1/dist/html-docx.min.js"></script>
<style>
.abc {
display: grid;
grid-template-columns: repeat(3, 1fr);
font-weight: bold;
}
.title {
font-weight: bold;
text-align: center;
vertical-align: middle;
}
.textCenter {
text-align: center;
}
tr,
td {
font-size: 12px;
}
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="content">
<div style="font-size: 48px; font-weight: bold; text-align: center">质量反馈单</div>
<div>反馈单单号: WLYD202412250049</div>
<table style="width: 100%;" border="1" cellspacing="0" cellpadding="0" class="textCenter">
<tr>
<td class="title">质量问题主题</th>
<td colspan="3" class="textCenter">
你还是是大家看会玩空间的哈授课计划的卡号夸奖哈首府卡迪夫好看就好的夸奖哈库文件很大看见你是法务会计贺卡就是饭卡文化按时付款计划啊空间未婚夫你还是是大家看玩空间的哈授课计划的卡号夸奖哈首府卡迪夫好看就好的夸奖哈库文件很大看见你是法务会计贺卡就是饭卡文化按时付款计划啊空间未婚夫你还是是大家看会玩空间的哈授课计划的卡号夸奖哈首府卡迪夫好看就好的夸奖哈库文件很大看见你是法务会计贺卡就是饭卡文化按时付款计划啊空间未婚夫
</td>
</tr>
<tr>
<td style="width: 15%;" class="title">反馈日期</td>
<td style="width: 35%;">2024-11-23</td>
<td style="width: 15%;" class="title">质量问题等级</td>
<td style="width: 35%;">严重</td>
</tr>
<tr>
<td class="title">电站名称</td>
<td>北京市超级充电站</td>
<td class="title">电站运营时间</td>
<td>2024-11-23</td>
</tr>
<tr>
<td class="title">项目类型</td>
<td>头肩</td>
<td class="title">反馈公司</td>
<td>特来电新能源</td>
</tr>
<tr>
<td class="title">反馈人</td>
<td>呆呆狗</td>
<td class="title">反馈人电话</td>
<td>18856491536</td>
</tr>
<tr>
<td class="title">父级设备</td>
<td>箱变</td>
<td class="title">设备生产日期</td>
<td>2024-11-23</td>
</tr>
<tr>
<td class="title">子型号</td>
<td>子星号</td>
<td class="title">故障设备</td>
<td>故障设备</td>
</tr>
</table>
<!-- 现场问题描述 -->
<table style="width: 100%;margin-top: -2px;" border="1" cellspacing="0" cellpadding="0">
<tr>
<td rowspan="2" style="width: 15%;" class="title">现场问题描述</td>
<td style="width: 85%;height: 100px;vertical-align:top">edddd</td>
</tr>
<tr style="height: 40px;">
<td>填写人: 呆呆狗</td>
</tr>
</table>
<!-- 纠正 -->
<table style="width: 100%;margin-top: -2px;" border="1" cellspacing="0" cellpadding="0">
<tr>
<td rowspan="7" style="width: 15%;text-align: center;" class="title">纠正</td>
<td colspan="2" style="width: 17%;text-align: center;" class="title">分类</td>
<td class="title" style="width: 10%;">数量</td>
<td class="title">措施</td>
<td class="title" style="width: 15%;">日期</td>
</tr>
<tr>
<td style="text-align: center;" colspan="2">现场故障设备</td>
<td class="textCenter">12345.00</td>
<td>3</td>
<td class="textCenter">2024-01-01</td>
</tr>
<tr>
<td rowspan="3" style="text-align: center;">在库</td>
<td style="text-align: center;">供应商在库</td>
<td class="textCenter">3</td>
<td>4</td>
<td class="textCenter">2024-01-01</td>
</tr>
<tr>
<td style="text-align: center;">XXX在库</td>
<td class="textCenter">3</td>
<td>4</td>
<td class="textCenter">2024-01-01</td>
</tr>
<tr>
<td style="text-align: center;">区域仓在库</td>
<td class="textCenter">3</td>
<td>4</td>
<td class="textCenter">2024-01-01</td>
</tr>
<tr>
<td style="text-align: center;" colspan="2">在市</td>
<td class="textCenter">2</td>
<td>3</td>
<td class="textCenter">2024-01-01</td>
</tr>
<tr>
<td style="text-align: center;" colspan="2">其他</td>
<td class="textCenter">2</td>
<td>3</td>
<td class="textCenter">2024-01-01</td>
</tr>
</table>
<!-- 具体原因分析 -->
<table style="width: 100%;margin-top: -2px;" border="1" cellspacing="0" cellpadding="0">
<tr>
<td rowspan="3" style="width: 15%;" class="title">原因分析</td>
<td style="width: 10%;" class="title">发生原因</td>
<td>2</td>
</tr>
<tr>
<td style="width: 10%;" class="title">流出原因</td>
<td>2</td>
</tr>
<tr>
<td style="width: 10%;" class="title">其他</td>
<td>2</td>
</tr>
</table>
<!-- 纠正措施 -->
<table style="width: 100%;margin-top: -2px;" border="1" cellspacing="0" cellpadding="0">
<tr>
<td rowspan="4" style="width: 15%;" class="title">纠正措施</td>
<td style="width: 10%;" class="title"></td>
<td class="title">措施</td>
<td style="width: 15%;" class="textCenter title">日期</td>
</tr>
<tr>
<td style="width: 10%;" class="title">发生</td>
<td>2</td>
<td style="width: 15%;" class="textCenter">2024-11-23</td>
</tr>
<tr>
<td style="width: 10%;" class="title">流出</td>
<td>2</td>
<td style="width: 15%;" class="textCenter">2024-11-23</td>
</tr>
<tr>
<td style="width: 10%;" class="title">举一反三</td>
<td>2</td>
<td style="width: 15%;" class="textCenter">2024-11-23</td>
</tr>
</table>
<!-- 标准化 -->
<table style="width: 100%;margin-top: -2px;" border="1" cellspacing="0" cellpadding="0">
<tr>
<td rowspan="3" style="width: 15%;" class="title">标准化</td>
<td class="title">文件名称</td>
<td style="width: 10%;" class="title">文件类型</td>
<td style="width: 15%;" class="title">日期</td>
</tr>
<tr>
<td>流出</td>
<td style="width: 10%;" class="textCenter">新增</td>
<td style="width: 15%;" class="textCenter">2024-11-23</td>
</tr>
<tr>
<td>举一反三</td>
<td style="width: 10%;" class="textCenter">修改</td>
<td style="width: 15%;" class="textCenter">2024-11-23</td>
</tr>
</table>
<!-- 责任部门 和 责任部门领导审批 -->
<table style="width: 100%;margin-top: -2px;" border="1" cellspacing="0" cellpadding="0">
<tr>
<td style="width: 15%;" class="title">责任部门</td>
<td class="textCenter">总裁办</td>
<td style="width: 10%;" class="title">负责人</td>
<td style="width: 15%;" class="textCenter">呆呆狗</td>
<td style="width: 10%;" class="title">日期</td>
<td style="width: 15%;" class="textCenter">2024-01-01</td>
</tr>
<tr>
<td style="width: 15%;" class="title">责任部门领导审批</td>
<td colspan="3" class="textCenter">总裁办</td>
<td style="width: 10%;" class="title">日期</td>
<td style="width: 15%;" class="textCenter">2024-01-01</td>
</tr>
</table>
<!-- 跟踪验证结果 -->
<table style="width: 100%;margin-top: -2px;" border="1" cellspacing="0" cellpadding="0">
<tr>
<td rowspan="3" style="width: 15%;" class="title">跟踪验证确认</td>
<td style="width: 85%;height: 100px;vertical-align:top">
缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结缺陷反酷点总结
</td>
</tr>
<tr style="height: 40px;">
<td>验证结果: 关闭 无效</td>
</tr>
<tr style="height: 40px;">
<td>负责人: 呆呆狗 日期:2024-12-30 </td>
</tr>
<tr>
<td style="width: 15%;font-family: '宋体';font-size: 12pt;" class="title">备注</td>
<td style="font-family: '宋体';font-size: 12pt"></td>
</tr>
</table>
</div>
<button id="downloadButton">Download as Word</button>
<script>
document.getElementById("downloadButton").onclick = function () {
var content = document.getElementById("content").outerHTML;
var fullHtml = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
* {
margin: 0;
padding: 0;
}
.title { font-weight: bold;text-align: center; vertical-align: middle;}
tr,
td {
font-size: 14px;
}
.textCenter {
text-align: center;
}
</style>
</head>
<body>
${content}
</body>
</html>
`;
var converted = htmlDocx.asBlob(fullHtml);
var link = document.createElement("a");
link.href = URL.createObjectURL(converted);
link.download = "document.docx";
link.click();
};
</script>
</body>
</html>
其实主要核心代码就是下面这几行
var converted = htmlDocx.asBlob(fullHtml);
var link = document.createElement("a");
link.href = URL.createObjectURL(converted);
link.download = "document.docx";
link.click();
用
html-docx-js
的asBlob
方法,传入前端的DOM ,然后,用URL.createObjectURL
创建一个blob 格式的链接,配合a标签
就可以了
2.2 前端生成word文件的样式
2.3 总结
优点
代码简单
,上手速度快- 不需要依赖于 后端,前端可以
独自处理
缺点
- 支持的 html、css 比较简单,比如
flex、grid
不支持 - 这个库已经
很久不维护
了 - 图片需要转成
base64
才能放进去 - word的
行高
、字体
、字号
支持性较差
如果对于 word 文件的样子要求不是很高,可以使用这个 方法,开发过程也相对比较简单
3、方式二:pizzip + docxtemplater
3.1 具体代码
核心思路
- 读取
预先
设置好的word 文件
解析word
,解析成二进制
- 创建docxtemplater实例
- 填充word 里面的数据
- 渲染word
- 获取渲染后word的 blob 地址
- 下载 word
前提需要
准备
一个这样的word 文件
,下面的代码是演示插入
和循环 table
,具体的文件在文章最顶部可以下载
这个word 里面的 语法可以参考这个链接 docxtemplater 语法演示
{Code} 在前端设置数据的时候,按照这个名字 和 要设置的值,组成 keyvalue 格式即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Docxtemplater Example</title>
<script src="https://cdn.jsdelivr.net/npm/pizzip@3.0.1/dist/pizzip.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/docxtemplater@3.29.0/build/docxtemplater.js"></script>
<script src="https://cdn.jsdelivr.net/npm/file-saver@2.0.5/dist/FileSaver.min.js"></script>
<script
src="https://unpkg.com/docxtemplater-image-module-free@3.0.0/dist/docxtemplater-image-module-free.js"></script>
</head>
<body>
<h1>Generate Word Document</h1>
<button id="generate">Download Word</button>
<script>
document.getElementById('generate').addEventListener('click', function () {
// 1、读取word 文件
fetch('./template.docx')
.then(response => response.arrayBuffer())
.then(arrayBuffer => {
console.log('第一步', arrayBuffer);
// 2、解析word
const zip = new PizZip(arrayBuffer);
// 3、创建docxtemplater实例
const doc = new window.docxtemplater(zip, {
paragraphLoop: true,
linebreaks: true,
});
// 4、设置数据
doc.setData({
Code: "ZLFX202412280001",
name: "你好啊啊John Doe阿斯顿我是具体措施111你是你好啊啊John Doe阿斯顿我是具体措施111你是你好啊啊John Doe阿斯顿我是具体措施111你是你好啊啊John Doe阿斯顿我是具体措施111你是",
arr: [
{ name: "第一行", type: "新增", time: "2024-12-23" },
{ name: "第二行", type: "修改", time: "2024-12-23" },
{ name: "第三行", type: "新增", time: "2024-12-23" },
{ name: "第四行", type: "新增", time: "2024-12-23" },
{ name: "第五行", type: "新增", time: "2024-12-23" },
{ name: "第六行", type: "新增", time: "2024-12-23" },
{ name: "第七行", type: "删除", time: "2099-12-23" },
],
});
try {
// 5、渲染word
doc.render();
} catch (error) {
console.error('Error rendering the document:', error);
return;
}
// 6、获取渲染后的word
const output = doc.getZip().generate({ type: 'blob' });
// 7、下载word
saveAs(output, 'output.docx');
})
.catch(error => console.error('Error loading template:', error));
});
</script>
</body>
</html>
3.2 前端生成word文件的样式
生成后的文件样式如下。
图片插入
这个地方 官方说是可以,其他的文章也有实现的,但这个地方我没实现。 据说是要用docxtemplater-image-module
这个库
3.3 总结
优点
- 样式可控制
缺点
2. 需要预先设置 word 文件的样式
4、参考链接
- docxtemplater 语法官方文档
- html-docx-js GitHub地址