工作中經(jīng)常會遇到根據(jù)不同數(shù)據(jù)導出文檔的情況场躯,現(xiàn)在我們就來看一下基于 docxtemplater 來導出word文檔的方法锐朴,使用起來非常便捷乃沙。
安裝依賴的插件
-- 安裝 docxtemplater
npm install docxtemplater pizzip --save
-- 安裝 jszip-utils
npm install jszip-utils --save
-- 安裝 jszip
npm install jszip --save
-- 安裝 FileSaver
npm install file-saver --save
下面簡單介紹一下這幾個插件的功能:
-
docxtemplater
:docxtemplate是一個從docx/pptx模板生成docx/pptx文檔的庫。語法包含變量替換科阎、條件判斷煤裙、循環(huán)、列表循環(huán)蛤吓、表格循環(huán)等,還包括圖片糠赦、html等模塊轉換扑毡。 -
jszip-utils
:jszip-utils是一個與 JSZip 一起使用的跨瀏覽器實用程序集合态蒂,詳細可參考 官網(wǎng)網(wǎng)址中的文檔袭景。 -
jszip
: jszip是一個JavaScript類庫帚屉,用來操作.zip文件的工具贮泞,詳細可參考 官方網(wǎng)址 中的文檔蘸鲸。 -
file-saver
:file-saver是在客戶端保存文件的解決方案荤堪,非常適合需要生成文件或者保存不應該發(fā)送到外部服務器的敏感信息的應用谜喊,詳細用法可參考 官方網(wǎng)址 中的文檔顺少。
創(chuàng)建exportFile.js(導出word方法)
- 引入依賴包
- 使用
jszip-utils
讀取并獲得模板文件的二進制內(nèi)容 - 使用
PizZip
創(chuàng)建實例朋其,內(nèi)容為模板的內(nèi)容 - 使用
docxtemplater
創(chuàng)建實例,并加載PizZip
創(chuàng)建的實例 - 使用
docxtemplater
創(chuàng)建實例設置導出數(shù)據(jù)脆炎,并用導出數(shù)據(jù)的值替換所有模板變量 - 生成一個代表docxtemplater對象的zip文件
- 使用
saveAs
將生成的zip文件對象保存為目標類型的文件梅猿,并命名
import PizZip from 'jszip';
import docxtemplater from 'docxtemplater';
import JSZipUtils from 'jszip-utils';
import { saveAs } from 'file-saver';
/**
* 導出word,支持圖片
* @param {Object} tempDocxPath 模板文件路徑
* @param {Object} wordData 導出數(shù)據(jù)
* @param {Object} fileName 導出文件名
*/
export const exportWord = (tempDocxPath, wordData, fileName) => {
// 讀取并獲得模板文件的二進制內(nèi)容
JSZipUtils.getBinaryContent(tempDocxPath, function (error, content) {
if (error) {
throw error;
}
// 創(chuàng)建一個PizZip實例,內(nèi)容為模板的內(nèi)容
const zip = new PizZip(content);
// 創(chuàng)建并加載docxtemplater實例對象
const doc = new docxtemplater();
doc.loadZip(zip);
doc.setData(wordData);
try {
// 用模板變量的值替換所有模板變量
doc.render();
} catch (error) {
// 拋出異常
const e = {
message: error.message,
name: error.name,
stack: error.stack,
properties: error.properties
};
console.log(
JSON.stringify({
error: e
})
);
throw error;
}
// 生成一個代表docxtemplater對象的zip文件(不是一個真實的文件秒裕,而是在內(nèi)存中的表示)
const out = doc.getZip().generate({
type: 'blob',
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
});
// 將目標文件對象保存為目標類型的文件袱蚓,并命名
saveAs(out, fileName);
}
);
};
編寫word文檔模板,具體的寫法可以參考 docxtemplater demo 上的例子
下面列出幾中常見的 docxtemplater
語法
- 替換
js中的變量定義:
{title:'簡介'}
word模板文件中語法:
{title}
- 循環(huán)
js中的變量定義:
{
loop:[
{ name: "Windows", price: 100},
{ name: "Mac OSX", price: 200 },
{ name: "Ubuntu", price: 0 }
],
userGreeting: (scope) => {
return "The product is" + scope.name + ", price:" + scope.price;
},
}
word模板文件中語法:
循環(huán){#loop}
{name}, {price}
// 匿名函數(shù)插槽用法
{userGreeting}
{/loop}
- 判斷
js中的變量定義:
{
hasKitty: true,
kitty: "Minie",
hasDog: false,
dog: "wangwang",
}
word模板文件中語法:
{#hasKitty}
Cat’s name: {kitty}
{/hasKitty}
{#hasDog}
Dog’s name: {dog}
{/hasDog}
- 圖片
js中的變量定義:
{
//文件路徑
image: '/logo.png',
}
word模板文件中語法:
{%image}
在組件中調(diào)用exportFile.js方法
import { exportWord } from '@/util/exportFile.js';
/**
* 參數(shù)1:模板文檔路徑
* 參數(shù)2:字段參數(shù)
* 參數(shù)3:輸出文檔
*/
const obj={
...
}
exportWord('template.docx' ,obj, '導出文件名.docx');
在這里關于模板文件的路徑 tempDocxPath
我們要著重說一下几蜻。
在使用的過程中應該有不少人會遇到這種報錯:Can't find end of central directory : is this a zip file ?
那這到底是什么原因導致的呢喇潘?
獲得模板文件的二進制內(nèi)容的方法,JSZipUtils.getBinaryContent(path, option) 提供path和option兩個參數(shù)梭稚。我們來看一下path颖低,前端開發(fā)最首先想到的可能是絕對路徑或者相對路徑,你可能還會用到@這個符號作為根目錄使用弧烤,但在這里你顯然不能這么用忱屑。
- 如果我們的模板文件為‘xxxx.docx’,那么我們的path應該為‘/xxxx.docx’。修改完這個地方之后莺戒,剩下的就是要知道你使用的vue-cli是版本2還是版本3伴嗡。如果是2,則應該有一個static的文件夾脏毯,請見你的模板文件放入這個static文件夾中闹究;如果是3,則有一個public文件夾食店,請將模板文件放入這個public文件夾中渣淤。
- 如果經(jīng)過上面的修改依然報錯,那么你就要看一下你的項目是不是微應用項目或者在項目路徑上做了什么處理吉嫩,如果是的話你需要根據(jù)項目目錄填寫xxxx.docx真正的路徑价认。