Vue前端導出Excel文件實現方案

1、技術選型

1.使用 vue-json-excel 插件實現

優勢:簡單便捷,易上手,開箱即用;javascript

缺點:不支持 excel 表格樣式設置,且支持功能比較單一;html

2.基於 sheetJS-xlsx 解析器的 xlsx-style 實現(推薦)

優勢:支持格式衆多,支持 excel 表格樣式設置,功能強大,可控性高,可讀取和導出excel;vue

缺點:使用較爲複雜,上手成本較大,且高級功能須要收費,但該功能能夠藉助 xlsx-style 實現;java

2、技術實現

使用 vue-json-excel 插件實現

1.安裝 vue-json-excel 依賴

npm install -S vue-json-excel
複製代碼

2.註冊插件到 vue 實例

import Vue from "vue";
import JsonExcel from "vue-json-excel";

Vue.component("downloadExcel", JsonExcel);
複製代碼

3.使用方式

在須要觸發導出事件的外出包裹 download-excel 組件ios

該組件支持的屬性可參考vue-json-excel 的 github 文檔git

<download-excel :data="json_data">
  Download Data
  <img src="download_icon.png" />
</download-excel>
複製代碼

首先須要處理導出到 excel 文件的數據內容,分別是如下數據:github

  • 表頭名數據 json_fields:能夠選擇要導出的字段,併爲字段分配標籤。該數據類型爲 Object ,key 對應的是標籤,value 對應的是 JSON 字段,將導出與數據列表相同字段的數據。若是須要自定義導出的數據,能夠定義回調函數。
  • 表格數據 json_data:該數據類型爲 Array,存儲了須要導出的數據內容;
let json_fields = {
  // fieldLabel(表頭名),attributeName(對應字段名)
  fieldLabel: attributeName,
  // 使用回調自定義導出數據
  anotherFieldLabel: {
    field: anotherAttributeName,
    callback: (value) => {
      return `formatted value ${value}`;
    },
  },
};

let json_data = [
    {
        attributeName: value1,
        anotherAttributeName: value2
    },
    {
        attributeName: value3,
        anotherAttributeName: value4
    }
];
複製代碼

處理完數據以後則能夠將數據傳入 download-excel 組件中,該組件沒有任何樣式,只須要設置內部包裹的元素樣式便可;web

<download-excel class="btn btn-default" :data="json_data" :fields="json_fields" worksheet="My Worksheet" name="filename.xls" >
  Download Excel (you can customize this with html code!)
</download-excel>
複製代碼

然而在實際的業務場景下,導出表格數據一般是導出表格的全部數據,因此在導出的過程當中,須要調用請求接口去獲取表格中的全部數據,而調用接口獲取數據是異步執行的過程,該插件也針對這個場景提供瞭解決方案。npm

相關案例:json

<template>
    <div id="app">
        <downloadexcel class = "btn" :fetch = "fetchData" :fields = "json_fields" :before-generate = "startDownload" :before-finish = "finishDownload">
            Download Excel
        </downloadexcel>
    </div>
</template>

<script> import downloadexcel from "vue-json-excel"; import axios from 'axios'; export default { name: "App", components: { downloadexcel, }, data(){ return { json_fields: { 'Complete name': 'name', 'Date': 'date', }, } }, //data methods:{ async fetchData(){ const response = await axios.get(URL); return response.data.holidays; }, startDownload(){ alert('show loading'); }, finishDownload(){ alert('hide loading'); } } }; </script>
複製代碼

基於 sheetJS-xlsx 解析器的 xlsx-style 實現(推薦)

因爲這部分涉及內容較多,後續有須要會封裝該功能

這裏只對封裝的 export2Excel 使用方法進行說明,暫時不對原理進行講解。

該插件不只支持 excel 文件的導出,也支持文件導入功能,而且導出 excel 文件的不只支持 json 數據,也支持 table 導出;

因爲 sheetjs-xlsx 提供的工具庫其高級功能是付費項目,如修改表格樣式等功能,所以選用了基於 sheetjs-xlsx 實現的 xlsx-style 插件。

兼容性:

1.安裝依賴

npm install -S xlsx
npm install -S xlsx-style
複製代碼

而 xlsx-style 插件在使用的時候會報錯,官方也對該問題給出瞭解決方案,就是在根目錄下的vue.config.js配置文件添加以下代碼:

module.exports = {
	configureWebpack: {
    	externals: {
      		'./cptable': 'var cptable'
    	}
  	}
}
複製代碼

還有一種方案是改源代碼,但不推薦使用,就不作說明了。

2.使用方法

這裏封裝了導出 excel 文件的方法,其中,文件下載的功能有兩個方案實現,分別是:

  • 經過 a 標籤的文件下載功能,利用 URL.createObjectURL 方法生成下載連接實現;(本文使用的方法)
  • 經過第三方插件 file-saver 插件實現文件下載功能;

js-xlsx 插件自帶了相關的函數去方便實現不一樣數據格式的轉換:

  • aoa_to_sheet converts an array of arrays of JS data to a worksheet.
  • json_to_sheet converts an array of JS objects to a worksheet.
  • table_to_sheet converts a DOM TABLE element to a worksheet.
  • sheet_add_aoa adds an array of arrays of JS data to an existing worksheet.
  • sheet_add_json adds an array of JS objects to an existing worksheet.

下面是封裝的 export2Excel 函數具體代碼,只須要將代碼複製到建立的 export2Excel.js 文件中便可:

/** * create by lwj * @file 導出export插件封裝 */

import * as styleXLSX from 'xlsx-style'

/** * 將 String 轉換成 ArrayBuffer * @method 類型轉換 * @param {String} [s] wordBook內容 * @return {Array} 二進制流數組 */
function s2ab (s) {
    let buf = null;

    if (typeof ArrayBuffer !== 'undefined') {
        buf = new ArrayBuffer(s.length);
        let view = new Uint8Array(buf);

        for (let i = 0; i != s.length; ++i) {
            view[i] = s.charCodeAt(i) & 0xFF;
        }

        return buf;
    }

    buf = new Array(s.length);

    for (let i = 0; i != s.length; ++i) {

        // 轉換成二進制流
        buf[i] = s.charCodeAt(i) & 0xFF;
    }

    return buf;
}

/** * 方案一:利用 URL.createObjectURL 下載 (如下選用) * 方案二:經過 file-saver 插件實現文件下載 * @method 文件下載 * @param {Object} [obj] 導出內容 Blob 對象 * @param {String} [fileName] 文件名 下載是生成的文件名 * @return {void} */ 
function saveAs (obj, fileName) {
    let aLink = document.createElement("a");

    if (typeof obj == 'object' && obj instanceof Blob) {
        aLink.href = URL.createObjectURL(obj); // 建立blob地址
    }
    
    aLink.download = fileName;
    aLink.click();
    setTimeout(function () {
        URL.revokeObjectURL(obj);
    }, 100);
}

/** * @method 數據導出excel * @param {Object} [worksheets] 工做表數據內容 * @param {String} [fileName='ExcelFile'] 導出excel文件名 * @param {String} [type='xlsx'] 導出文件類型 */
export default function export2Excel ({ worksheets, fileName = 'ExcelFile', type = 'xlsx' } = {}) {

    let sheetNames = Object.keys(worksheets);
    let workbook = {
        SheetNames: sheetNames, //保存的工做表名
        Sheets: worksheets
    };

    // excel的配置項
    let wopts = {  
        bookType: type,  // 生成的文件類型
        bookSST: false, // 是否生成Shared String Table,官方解釋是,若是開啓生成速度會降低,但在低版本IOS設備上有更好的兼容性
        type: 'binary'  
    }

    // attempts to write the workbook
    let wbout = styleXLSX.write(workbook, wopts);
    let wbBlob = new Blob([s2ab(wbout)], {
        type: "application/octet-stream"
    });

    saveAs(wbBlob, fileName + '.' + type);
}
複製代碼

須要注意幾個問題:

  1. xlsx 和 xlsx-style 的默認導出函數名都是 XLSX ,若是同時導入的話,須要注意設置別名,避免函數覆蓋出現問題;
  2. 若是不想使用 xlsx 插件,只使用 xlsx-style 插件一樣也是能夠的,只是要本身將須要導出的數據轉換成 worksheet 格式對象,其原理也就是將導出數據轉換成 worksheet 規定的數據格式,具體能夠查看 js-xlsx 文檔說明;(能夠本身嘗試實現)

而後只須要在須要導出 excel 的地方調用便可,若是對導出表格樣式有要求的狀況下,能夠去了解如何配置表格樣式,具體配置方法能夠去 xlsx-style 文檔 中查看。

若是是 json 數據導出,須要對錶頭名和字段進行映射;

相關案例:

import XLSX from 'xlsx';
import export2Excel from '@/assets/utils/export2Excel';

// json 格式
let jsonTable = [{
    "sheet1id": 1,
    "表頭1": "數據11",
    "表頭2": "數據12",
    "表頭3": "數據13",
    "表頭4": "數據14"
}, {
    "sheet1id": 2, 
    "表頭1": "數據21",
    "表頭2": "數據22",
    "表頭3": "數據23",
    "表頭4": "數據24"
}];

// 二維數組格式
let aoa = [
    ['sheet2id', '表頭1', '表頭2', '表頭3', '表頭4'],
    [1, '數據11', '數據12', '數據13', '數據14'],
    [2, '數據21', '數據22', '數據23', '數據24']
]

function handleExportExcel () {
    
    // 使用 XLSX 內置的工具庫將 json 轉換成 sheet
    let worksheet1 = XLSX.utils.json_to_sheet(jsonTable);

    // 使用 XLSX 內置的工具庫將 aoa 轉換成 sheet
    let worksheet2 = XLSX.utils.aoa_to_sheet(aoa);

    // 設置 excel 表格樣式
    worksheet1["B1"].s = { 
        font: { 
            sz: 14, 
            bold: true, 
            color: { 
                rgb: "FFFFAA00"
            } 
        }, 
        fill: { 
            bgColor: { 
                indexed: 64 
            }, 
            fgColor: { 
                rgb: "FFFF00" 
            } 
        } 
    };

    // 單元格合併
    worksheet1["!merges"] = [{
        s: { c: 1, r: 0 },
        e: { c: 4, r: 0 }
    }];

    export2Excel({
        worksheets: {
            sheet1: worksheet1,
            sheet2: worksheet2
        }, // 導出excel的數據,key表示工做表名,value表示對應工做表的 sheet 數據,支持導出多個工做表
        fileName: '個人excel', // 導出文件名
        type: 'xlsx' // 文件導出類型
    });
}
複製代碼

3、參考資料

相關文章
相關標籤/搜索