摘要:之前專案中匯出價格表是由後端實現,前端只需要呼叫介面下載word即可,後來業務改變比較大,word模版需要一直改動,後端改起來相對麻煩,後來直接前端自己定義模版,實現下載word文件。
一、需要安裝的依賴
1、docxtemplater
介紹:docxtemplater是一種郵件合併工具,它以程式設計方式使用,處理條件、迴圈,並且可以擴充套件為表格、HTML、影像等。
安裝方法:cnpm i docxtemplater@^3.9.1
2、FileSaver
介紹:FileSaver.js 是在客戶端儲存檔案的解決方案,非常適合需要生成檔案,或者儲存不應該傳送到外部伺服器的敏感資訊的應用。
安裝方法:cnpm i file-saver@^1.3.8
3、jszip
介紹:jszip是一個用於建立、讀取和編輯.zip檔案的JavaScript庫,且API的使用也很簡單。
安裝方法:cnpm i jszip@^2.6.1
4、jszip-utils
介紹:jszip-utils是與jszip一起使用的跨瀏覽器的工具庫
安裝方法:cnpm i jszip-utils@^0.0.2
二、建立word模版
介紹:根據自己的業務需求建立需要匯出的word模版,變數資料使用{變數名}代替,表格內容資料需要使用{#引數名}開始{/引數名}結尾,具體如下圖:
注意點:1.模板檔案使用vue-cli2的時候,放在static目錄下。使用vue-cli3的時候,放在public目錄下。
2.檔案須以docx結尾。
不然可能出現的問題:提示Uncaught Error: Corrupted zip: missing 7124 bytes.
vue-cli3示例位置如圖:
三、html程式碼編寫
定義下載事件downloadprice
<div class="download” @click="downloadprice">下載價格表</div>
四、script程式碼編寫
1.使用的頁面中匯入需要的外掛:
import Docxtemplater from 'docxtemplater'; import { saveAs } from 'file-saver'; import JSZip from 'jszip'; import JSZipUtils from 'jszip-utils';
2.定義介面資料(這裡為定義好的資料,正常情況下通過介面獲取需要在word文件上展示的資料):
data() {
return {
// 匯出價格表全部資訊
exportPriceObj: {
actualPayFee: '179.55',
deliveryFee: '0.00',
discountActualFee: '179.55',
discountFee: '9.45',
discountRatio: '95',
nickName: '張三',
retailTotalFee: '0.00',
totalFee: '189.00',
},
// 匯出價格表商品資訊
exportPriceListOne: [
{
productColor: '白色',
productName: '0909測試商品',
productNo: 1,
productSize: '4XL(58)',
productSkuId: 'teydnkn',
sellingPrice: '10.00',
},
{
productColor: '白色',
productName: '1955測試商品',
productNo: 2,
productSize: 'XL(52)',
productSkuId: 'teydoja',
sellingPrice: '40.00',
}
],
}
}
3.下載word文件點選事件方法:
// 下載價格表 downloadprice() { let _this = this; // 判斷有無附加商品來選擇word模版 // 讀取並獲得模板檔案的二進位制內容 JSZipUtils.getBinaryContent('pricenew.docx', function(error, content) { console.log('-----', content); // input.docx是模板。我們在匯出的時候,會根據此模板來匯出對應的資料 // 丟擲異常 if (error) { throw error; } // 建立一個JSZip例項,內容為模板的內容 let zip = new JSZip(content); console.log('+++++', zip); // 建立並載入docxtemplater例項物件 let doc = new Docxtemplater(); console.log('/////', doc); doc.loadZip(zip); console.log('=====', doc); // 設定模板變數的值 doc.setData({ // 匯出價格表全部資訊 ..._this.exportPriceObj, // 匯出價格表商品資訊 tableone: _this.exportPriceListOne, }); try { // 用模板變數的值替換所有模板變數 doc.render(); } catch (error) { // 丟擲異常 let e = { message: error.message, name: error.name, stack: error.stack, properties: error.properties }; console.log(JSON.stringify({ error: e })); throw error; } // 生成一個代表docxtemplater物件的zip檔案(不是一個真實的檔案,而是在記憶體中的表示) let out = doc.getZip().generate({ type: 'blob', mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }); // 將目標檔案物件儲存為目標型別的檔案,並命名 saveAs(out, _this.exportPriceObj.nickName + '的價格表.docx'); }); },
4.點選下載後可能會出現的問題:
一、提示Uncaught Error: Corrupted zip: missing 7124 bytes.
錯誤方法如圖:
可能產生的原因是:1.模版檔案word放置的位置獲取不到;
2.word文件格式出現錯誤;
解決方法:1.模板檔案使用vue-cli2的時候,放在static目錄下。使用vue-cli3的時候,放在public目錄下。
2.檔案須以docx結尾。
正確方法如圖:
二、提示Uncaught Error: Can't find end of central directory : is this a zip file ?
錯誤方法如圖:
可能產生的原因是:1.你專案裡面引用了mockjs檔案,它的原理是重寫了XMLHttpRequest,導致你上報外掛找不到對應的方法;
解決方法:上線時把專案中引入的mock註釋掉,// import '@/mock';
原理分析:mockjs是一個模擬後臺介面的JS庫,它的原理是重寫了XMLHttpRequest,它可以在介面沒出來時非常方便的模擬資料,上線之後 不引用它即可。一般上報外掛中會使用原生XMLHttpRequest,而原生XMLHttpRequest已被mockjs覆蓋找不到相應的方法,所以會 出錯。除了mockjs之外,zonejs、oboejs、fetchjs也有自己的的XMLHttpRequest庫,請慎用。
正確方法如圖:
五、匯出結果
匯出結果如圖:
有問題歡迎留言,帶上問題和程式碼截圖,看到後第一時間回覆幫忙解答,謝謝!