前端生成word文件的兩種方式總結(jié)
1、背景
在實(shí)際開發(fā)中,業(yè)務(wù)需要,需要把數(shù)據(jù)進(jìn)行組合生成一個(gè) word 文件
2、方式一:html-docx-js

注意,這個(gè)插件 最近的更新日期 八年之前了
2.1 具體代碼
核心邏輯
- 畫出 Word 文件內(nèi)容樣子
- 把 word文件內(nèi)容樣子的
DOM。傳入html-docx-js的asBlob方法 - 處理
blob格式的數(shù)據(jù),配合 a 標(biāo)簽,直接在界面彈出文件

<!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">質(zhì)量反饋單</div>
<div>反饋單單號(hào): WLYD202412250049</div>
<table style="width: 100%;" border="1" cellspacing="0" cellpadding="0" class="textCenter">
<tr>
<td class="title">質(zhì)量問題主題</th>
<td colspan="3" class="textCenter">
你還是是大家看會(huì)玩空間的哈授課計(jì)劃的卡號(hào)夸獎(jiǎng)哈首府卡迪夫好看就好的夸獎(jiǎng)哈庫文件很大看見你是法務(wù)會(huì)計(jì)賀卡就是飯卡文化按時(shí)付款計(jì)劃啊空間未婚夫你還是是大家看玩空間的哈授課計(jì)劃的卡號(hào)夸獎(jiǎng)哈首府卡迪夫好看就好的夸獎(jiǎng)哈庫文件很大看見你是法務(wù)會(huì)計(jì)賀卡就是飯卡文化按時(shí)付款計(jì)劃啊空間未婚夫你還是是大家看會(huì)玩空間的哈授課計(jì)劃的卡號(hào)夸獎(jiǎng)哈首府卡迪夫好看就好的夸獎(jiǎng)哈庫文件很大看見你是法務(wù)會(huì)計(jì)賀卡就是飯卡文化按時(shí)付款計(jì)劃啊空間未婚夫
</td>
</tr>
<tr>
<td style="width: 15%;" class="title">反饋日期</td>
<td style="width: 35%;">2024-11-23</td>
<td style="width: 15%;" class="title">質(zhì)量問題等級</td>
<td style="width: 35%;">嚴(yán)重</td>
</tr>
<tr>
<td class="title">電站名稱</td>
<td>北京市超級充電站</td>
<td class="title">電站運(yùn)營時(shí)間</td>
<td>2024-11-23</td>
</tr>
<tr>
<td class="title">項(xiàng)目類型</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">父級設(shè)備</td>
<td>箱變</td>
<td class="title">設(shè)備生產(chǎn)日期</td>
<td>2024-11-23</td>
</tr>
<tr>
<td class="title">子型號(hào)</td>
<td>子星號(hào)</td>
<td class="title">故障設(shè)備</td>
<td>故障設(shè)備</td>
</tr>
</table>
<!-- 現(xiàn)場問題描述 -->
<table style="width: 100%;margin-top: -2px;" border="1" cellspacing="0" cellpadding="0">
<tr>
<td rowspan="2" style="width: 15%;" class="title">現(xiàn)場問題描述</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%;">數(shù)量</td>
<td class="title">措施</td>
<td class="title" style="width: 15%;">日期</td>
</tr>
<tr>
<td style="text-align: center;" colspan="2">現(xiàn)場故障設(shè)備</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;">供應(yīng)商在庫</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;">區(qū)域倉在庫</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">發(fā)生原因</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">發(fā)生</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>
<!-- 標(biāo)準(zhǔn)化 -->
<table style="width: 100%;margin-top: -2px;" border="1" cellspacing="0" cellpadding="0">
<tr>
<td rowspan="3" style="width: 15%;" class="title">標(biāo)準(zhǔn)化</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>
<!-- 責(zé)任部門 和 責(zé)任部門領(lǐng)導(dǎo)審批 -->
<table style="width: 100%;margin-top: -2px;" border="1" cellspacing="0" cellpadding="0">
<tr>
<td style="width: 15%;" class="title">責(zé)任部門</td>
<td class="textCenter">總裁辦</td>
<td style="width: 10%;" class="title">負(fù)責(zé)人</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">責(zé)任部門領(lǐng)導(dǎo)審批</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>
<!-- 跟蹤驗(yàn)證結(jié)果 -->
<table style="width: 100%;margin-top: -2px;" border="1" cellspacing="0" cellpadding="0">
<tr>
<td rowspan="3" style="width: 15%;" class="title">跟蹤驗(yàn)證確認(rèn)</td>
<td style="width: 85%;height: 100px;vertical-align:top">
缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)缺陷反酷點(diǎn)總結(jié)
</td>
</tr>
<tr style="height: 40px;">
<td>驗(yàn)證結(jié)果: 關(guān)閉 無效</td>
</tr>
<tr style="height: 40px;">
<td>負(fù)責(zé)人: 呆呆狗 日期: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>
其實(shí)主要核心代碼就是下面這幾行
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創(chuàng)建一個(gè)blob 格式的鏈接,配合a標(biāo)簽就可以了
2.2 前端生成word文件的樣式


2.3 總結(jié)
優(yōu)點(diǎn)
- 代碼簡單,上手速度快
- 不需要依賴于 后端,前端可以獨(dú)自處理
缺點(diǎn)
- 支持的 html、css 比較簡單,比如
flex、grid不支持 - 這個(gè)庫已經(jīng)很久不維護(hù)了
- 圖片需要轉(zhuǎn)成
base64才能放進(jìn)去 - word的 行高、字體、字號(hào) 支持性較差
如果對于 word 文件的樣子要求不是很高,可以使用這個(gè) 方法,開發(fā)過程也相對比較簡單
3、方式二:pizzip + docxtemplater
3.1 具體代碼

核心思路
- 讀取預(yù)先設(shè)置好的 word 文件
- 解析word ,解析成二進(jìn)制
- 創(chuàng)建docxtemplater實(shí)例
- 填充word 里面的數(shù)據(jù)
- 渲染word
- 獲取渲染后word的 blob 地址
- 下載 word
前提需要準(zhǔn)備一個(gè)這樣的word 文件 ,下面的代碼是演示 插入 和 循環(huán) table,具體的文件在文章最頂部可以下載
這個(gè)word 里面的 語法可以參考這個(gè)鏈接 docxtemplater 語法演示
{Code} 在前端設(shè)置數(shù)據(jù)的時(shí)候,按照這個(gè)名字 和 要設(shè)置的值,組成 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、創(chuàng)建docxtemplater實(shí)例
const doc = new window.docxtemplater(zip, {
paragraphLoop: true,
linebreaks: true,
});
// 4、設(shè)置數(shù)據(jù)
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文件的樣式
生成后的文件樣式如下。 圖片插入這個(gè)地方 官方說是可以,其他的文章也有實(shí)現(xiàn)的,但這個(gè)地方我沒實(shí)現(xiàn)。 據(jù)說是要用
docxtemplater-image-module這個(gè)庫

3.3 總結(jié)
優(yōu)點(diǎn)
- 樣式可控制
缺點(diǎn)
2. 需要預(yù)先設(shè)置 word 文件的樣式
4、參考鏈接
到此這篇關(guān)于前端生成word文件的兩種方式的文章就介紹到這了,更多相關(guān)前端生成word 文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS圖片延遲加載插件LazyImgv1.0用法分析【附demo源碼下載】
這篇文章主要介紹了JS圖片延遲加載插件LazyImgv1.0用法,結(jié)合實(shí)例形式分析了使用圖片延遲加載插件LazyImgv1.0的注意事項(xiàng)與核心操作技巧,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下2017-09-09
javascript中的undefined 與 null 的區(qū)別 補(bǔ)充篇
在Javascript中有兩個(gè)值用來代表類似空值的概念,undefined和null,這兩個(gè)很容易被混淆,他們表示的是兩個(gè)不同的概念。2010-03-03
前端頁面適配之postcss-px-to-viewport實(shí)現(xiàn)步驟
postcss-px-to-viewport是一個(gè)PostCSS插件,它可以將px單位轉(zhuǎn)換為視口單位(vw、vh?或?vmin),這篇文章主要給大家介紹了關(guān)于前端頁面適配之postcss-px-to-viewport的實(shí)現(xiàn)步驟,需要的朋友可以參考下2024-03-03
基于canvas實(shí)現(xiàn)的絢麗圓圈效果完整實(shí)例
這篇文章主要介紹了基于canvas實(shí)現(xiàn)的絢麗圓圈效果,以完整實(shí)例形式分析了JavaScript結(jié)合html5的canvas實(shí)現(xiàn)動(dòng)態(tài)圖形的繪制技巧,需要的朋友可以參考下2016-01-01
原生js實(shí)現(xiàn)移動(dòng)端Touch輪播圖的方法步驟
這篇文章主要介紹了原生js實(shí)現(xiàn)移動(dòng)端Touch輪播圖的方法步驟,touch輪播圖其實(shí)就是通過手指的滑動(dòng),來左右切換輪播圖,touch輪播圖其實(shí)就是通過手指的滑動(dòng),來左右切換輪播圖,2019-01-01

