vue專案前端匯出word檔案(bug解決)

騎碼行天下發表於2020-09-11

摘要:之前專案中匯出價格表是由後端實現,前端只需要呼叫介面下載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之外,zonejsoboejsfetchjs也有自己的的XMLHttpRequest庫,請慎用。

正確方法如圖:

 

五、匯出結果

匯出結果如圖:

有問題歡迎留言,帶上問題和程式碼截圖,看到後第一時間回覆幫忙解答,謝謝!

 

相關文章