Vue+Element 實現excel的導入導出


Vue+Element 實現excel的導入導出

在最近項目中,用到了模板下載與批量上傳的功能,下面是實現步驟(本地環境是@vue/cli 4.3.1+element,vue2.0可能會有報錯,自行調整即可)

一、環境安裝

1、先安裝相關依賴

1 npm install -S xlsx file-saver 2 npm install -D script-loader

2、依賴裝完之后,還需要准備兩個js文件,分別是Blob.js和Export2Excel.js(這兩個文件在文章末尾有源碼),將兩個文件放在項目指定目錄中。我是放在里src目錄下的utils中,放在其他目錄也可以

二、excel文件導出

1、在相應vue文件中,定義觸發導出excel文件的方法

1 <div class="insured-btn-div">
2     <el-button type="primary" size="small" @click="handleExport">模板下載</el-button>
3 </div>

2、再引入Export2Excel.js即可,源碼如下

 1 //模板下載
 2 handleExport() {  3     require.ensure([], () => {  4         const { export_json_to_excel } = require('@/utils/Export2Excel');  5         console.log(this.insured);  6         let tHeader = [];  7         if (this.insured.length > 0) {  8             //從insured中提取標題
 9             this.insured.forEach(item=>{ 10  tHeader.push(item.name); 11  }) 12  } 13         export_json_to_excel(tHeader, [], '被保險人信息模板'); 14         return false; 15  }) 16 },

注意:我的模板下載是一個只有標題的空excel,而且標題是直接從其他地方獲取的,為了更好理解,再給出一個簡單示例

 1 // 下載
 2 handleExport() {  3     require.ensure([], () => {  4  const {  5  export_json_to_excel  6         } = require('vendor/Export2Excel');  7         const tHeader = ['序號', '文章標題', '作者', '閱讀數', '發布時間'];  8         const filterVal = ['id', 'title', 'author', 'views', 'display_time'];  9         const list = [ 10             {id: 1, title: 2, author: 3, pageviews: 4, display_time: 5}, 11             {id: 6, title: 7, author: 8, pageviews: 9, display_time: 10}, 12             {id: 11, title: 12, author: 13, pageviews: 14, display_time: 15}, 13  ]; 14         const data = this.formatJson(filterVal, list); 15         export_json_to_excel(tHeader, data, '列表excel'); 16  }) 17 },

我的模板下載后是這樣的:

簡單示例得到的excel文件是這樣的:由於filterVal中是views,而list中是pageviews,所以得到的閱讀數那一欄都是空的

三、excel文件導出

模板下載之后,按照格式填寫對應的數據,再上傳解析

1、這是觸發文件導出的方法,action="",不上傳服務器,只是解析excel中的數據而已

 1 <div class="insured-btn-div">
 2     <el-upload  3         class="upload-demo"
 4         action=""
 5         :on-change="handleChange"
 6         :show-file-list="false"
 7         accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel"
 8         :auto-upload="false">
 9         <el-button size="small" type="primary">批量上傳</el-button>
10     </el-upload>
11 </div>

2、解析excel文件的方法

 1 //上傳文件
 2 handleChange(file, fileList){  3     var f = file.raw;// 獲取文件內容
 4     // 通過DOM取文件數據
 5     var rABS = false; //是否將文件讀取為二進制字符串
 6     var reader = new FileReader();  7     var that = this;  8     //if (!FileReader.prototype.readAsBinaryString) {
 9     FileReader.prototype.readAsBinaryString = function(f) { 10         var binary = ""; 11         var rABS = false; //是否將文件讀取為二進制字符串
12         var wb; //讀取完成的數據
13         var outdata; 14         var reader = new FileReader(); 15         reader.onload = function(e) { 16             var bytes = new Uint8Array(reader.result); 17             var length = bytes.byteLength; 18             for(var i = 0; i < length; i++) { 19                 binary += String.fromCharCode(bytes[i]); 20  } 21             var XLSX = require('xlsx'); 22             if(rABS) { 23                 wb = XLSX.read(btoa(fixdata(binary)), { //手動轉化
24                     type: 'base64'
25  }); 26             } else { 27                 wb = XLSX.read(binary, { 28                     type: 'binary'
29  }); 30  } 31             outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);//outdata就是你想要的東西
32             this.da = [...outdata] //這就是excel文件中的數據
33             // let arr = [];
34             // 下面是數據解析提取邏輯
35             if (that.insured.length > 0) { 36                 //首先清空之前的被保人數據
37                 that.insureTemplate.id = 0;//將模板id重置為0;
38                 that.insureLength = 0; // 將投保人數據長度變為0
39                 that.form.insuredTableData = [];//將投保人數據清空
40                 for (let v of this.da) { 41                     // 判斷是否超出批量投保最大份數
42                     if (that.insureTemplate.id >= that.product.batch_bill_max) { 43                         break; 44  } 45                     let obj = {}; 46                     that.insureTemplate.id += 1; 47                     obj.id = that.insureTemplate.id; 48                     that.insured.forEach(j=>{ 49                         if (v.hasOwnProperty(j.name)) { 50                             obj[j.field] = v[j.name]; 51                         } else { 52                             //模板里沒有填的字段,直接賦空值
53                             obj[j.field] = ''; 54  } 55  }); 56                     // 提取被保人的生日及性別
57                     if (obj.hasOwnProperty('insureder_cert_num')) { 58                         let res = that.getBirthdayAndGenderByNum(obj.insureder_cert_num); 59                         if (res[0] != 0) { 60                             if (obj.hasOwnProperty('insureder_birthdate')) { 61                                 obj.insureder_birthdate = res[0]; 62  } 63                             if (obj.hasOwnProperty('insureder_sex')) { 64                                 if (res[1] == 0) { 65                                     //注意這個男女ID和后台對應
66                                     obj.insureder_sex = 49; 67                                 } else { 68                                     obj.insureder_sex = 48; 69  } 70  } 71  } 72  } 73                     obj.price = '0.00'; 74  that.form.insuredTableData.push(obj); 75                     // obj.code = v['被保人姓名']
76                     // obj.type = v['被保人手機號']
77                     // arr.push(obj)
78  } 79                 that.insureLength = that.insureTemplate.id; 80  } 81             // return arr
82  } 83  reader.readAsArrayBuffer(f); 84  } 85 
86     if(rABS) { 87  reader.readAsArrayBuffer(f); 88     } else { 89  reader.readAsBinaryString(f); 90  } 91     
92 }

這是模板文件中填寫的數據

最后再貼上Blob.js和Export2Excel.js的源碼

Blob.js

 1 /* eslint-disable */
 2 /* Blob.js  3  * A Blob implementation.  4  * 2014-05-27  5  *  6  * By Eli Grey, http://eligrey.com  7  * By Devin Samarin, https://github.com/eboyjr  8  * License: X11/MIT  9  * See LICENSE.md  10  */
 11 
 12 /*global self, unescape */
 13 /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,  14  plusplus: true */
 15 
 16 /*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
 17 
 18 (function (view) {  19     "use strict";  20 
 21     view.URL = view.URL || view.webkitURL;  22 
 23     if (view.Blob && view.URL) {  24         try {  25             new Blob;  26             return;  27         } catch (e) {}  28  }  29 
 30     // Internally we use a BlobBuilder implementation to base Blob off of
 31     // in order to support older browsers that only have BlobBuilder
 32     var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) {  33             var
 34                 get_class = function(object) {  35                     return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];  36  }  37                 , FakeBlobBuilder = function BlobBuilder() {  38                     this.data = [];  39  }  40                 , FakeBlob = function Blob(data, type, encoding) {  41                     this.data = data;  42                     this.size = data.length;  43                     this.type = type;  44                     this.encoding = encoding;  45  }  46                 , FBB_proto = FakeBlobBuilder.prototype  47                 , FB_proto = FakeBlob.prototype  48                 , FileReaderSync = view.FileReaderSync  49                 , FileException = function(type) {  50                     this.code = this[this.name = type];  51  }  52                 , file_ex_codes = (  53                     "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
 54                     + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
 55                 ).split(" ")  56                 , file_ex_code = file_ex_codes.length  57                 , real_URL = view.URL || view.webkitURL || view  58                 , real_create_object_URL = real_URL.createObjectURL  59                 , real_revoke_object_URL = real_URL.revokeObjectURL  60                 , URL = real_URL  61                 , btoa = view.btoa  62                 , atob = view.atob  63 
 64                 , ArrayBuffer = view.ArrayBuffer  65                 , Uint8Array = view.Uint8Array  66  ;  67             FakeBlob.fake = FB_proto.fake = true;  68             while (file_ex_code--) {  69                 FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;  70  }  71             if (!real_URL.createObjectURL) {  72                 URL = view.URL = {};  73  }  74             URL.createObjectURL = function(blob) {  75                 var
 76                     type = blob.type  77  , data_URI_header  78  ;  79                 if (type === null) {  80                     type = "application/octet-stream";  81  }  82                 if (blob instanceof FakeBlob) {  83                     data_URI_header = "data:" + type;  84                     if (blob.encoding === "base64") {  85                         return data_URI_header + ";base64," + blob.data;  86                     } else if (blob.encoding === "URI") {  87                         return data_URI_header + "," + decodeURIComponent(blob.data);  88                     } if (btoa) {  89                         return data_URI_header + ";base64," + btoa(blob.data);  90                     } else {  91                         return data_URI_header + "," + encodeURIComponent(blob.data);  92  }  93                 } else if (real_create_object_URL) {  94                     return real_create_object_URL.call(real_URL, blob);  95  }  96  };  97             URL.revokeObjectURL = function(object_URL) {  98                 if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {  99  real_revoke_object_URL.call(real_URL, object_URL); 100  } 101  }; 102             FBB_proto.append = function(data/*, endings*/) { 103                 var bb = this.data; 104                 // decode data to a binary string
105                 if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) { 106                     var
107                         str = ""
108                         , buf = new Uint8Array(data) 109                         , i = 0
110                         , buf_len = buf.length 111  ; 112                     for (; i < buf_len; i++) { 113                         str += String.fromCharCode(buf[i]); 114  } 115  bb.push(str); 116                 } else if (get_class(data) === "Blob" || get_class(data) === "File") { 117                     if (FileReaderSync) { 118                         var fr = new FileReaderSync; 119  bb.push(fr.readAsBinaryString(data)); 120                     } else { 121                         // async FileReader won't work as BlobBuilder is sync
122                         throw new FileException("NOT_READABLE_ERR"); 123  } 124                 } else if (data instanceof FakeBlob) { 125                     if (data.encoding === "base64" && atob) { 126  bb.push(atob(data.data)); 127                     } else if (data.encoding === "URI") { 128  bb.push(decodeURIComponent(data.data)); 129                     } else if (data.encoding === "raw") { 130  bb.push(data.data); 131  } 132                 } else { 133                     if (typeof data !== "string") { 134                         data += ""; // convert unsupported types to strings
135  } 136                     // decode UTF-16 to binary string
137  bb.push(unescape(encodeURIComponent(data))); 138  } 139  }; 140             FBB_proto.getBlob = function(type) { 141                 if (!arguments.length) { 142                     type = null; 143  } 144                 return new FakeBlob(this.data.join(""), type, "raw"); 145  }; 146             FBB_proto.toString = function() { 147                 return "[object BlobBuilder]"; 148  }; 149             FB_proto.slice = function(start, end, type) { 150                 var args = arguments.length; 151                 if (args < 3) { 152                     type = null; 153  } 154                 return new FakeBlob( 155                     this.data.slice(start, args > 1 ? end : this.data.length) 156  , type 157                     , this.encoding 158  ); 159  }; 160             FB_proto.toString = function() { 161                 return "[object Blob]"; 162  }; 163             FB_proto.close = function() { 164                 this.size = this.data.length = 0; 165  }; 166             return FakeBlobBuilder; 167  }(view)); 168 
169     view.Blob = function Blob(blobParts, options) { 170         var type = options ? (options.type || "") : ""; 171         var builder = new BlobBuilder(); 172         if (blobParts) { 173             for (var i = 0, len = blobParts.length; i < len; i++) { 174  builder.append(blobParts[i]); 175  } 176  } 177         return builder.getBlob(type); 178  }; 179 }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));

Export2Excel.js

 1 /* eslint-disable */
 2 require('script-loader!file-saver');  3 require('@/utils/Blob');  4 require('script-loader!xlsx/dist/xlsx.core.min');  5 function generateArray(table) {  6     var out = [];  7     var rows = table.querySelectorAll('tr');  8     var ranges = [];  9     for (var R = 0; R < rows.length; ++R) {  10         var outRow = [];  11         var row = rows[R];  12         var columns = row.querySelectorAll('td');  13         for (var C = 0; C < columns.length; ++C) {  14             var cell = columns[C];  15             var colspan = cell.getAttribute('colspan');  16             var rowspan = cell.getAttribute('rowspan');  17             var cellValue = cell.innerText;  18             if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;  19 
 20             //Skip ranges
 21             ranges.forEach(function (range) {  22                 if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {  23                     for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);  24  }  25  });  26 
 27             //Handle Row Span
 28             if (rowspan || colspan) {  29                 rowspan = rowspan || 1;  30                 colspan = colspan || 1;  31                 ranges.push({s: {r: R, c: outRow.length}, e: {r: R + rowspan - 1, c: outRow.length + colspan - 1}});  32  }  33  ;  34 
 35             //Handle Value
 36             outRow.push(cellValue !== "" ? cellValue : null);  37 
 38             //Handle Colspan
 39             if (colspan) for (var k = 0; k < colspan - 1; ++k) outRow.push(null);  40  }  41  out.push(outRow);  42  }  43     return [out, ranges];  44 };  45 
 46 function datenum(v, date1904) {  47     if (date1904) v += 1462;  48     var epoch = Date.parse(v);  49     return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);  50 }  51 
 52 function sheet_from_array_of_arrays(data, opts) {  53     var ws = {};  54     var range = {s: {c: 10000000, r: 10000000}, e: {c: 0, r: 0}};  55     for (var R = 0; R != data.length; ++R) {  56         for (var C = 0; C != data[R].length; ++C) {  57             if (range.s.r > R) range.s.r = R;  58             if (range.s.c > C) range.s.c = C;  59             if (range.e.r < R) range.e.r = R;  60             if (range.e.c < C) range.e.c = C;  61             var cell = {v: data[R][C]};  62             if (cell.v == null) continue;  63             var cell_ref = XLSX.utils.encode_cell({c: C, r: R});  64 
 65             if (typeof cell.v === 'number') cell.t = 'n';  66             else if (typeof cell.v === 'boolean') cell.t = 'b';  67             else if (cell.v instanceof Date) {  68                 cell.t = 'n';  69                 cell.z = XLSX.SSF._table[14];  70                 cell.v = datenum(cell.v);  71  }  72             else cell.t = 's';  73 
 74             ws[cell_ref] = cell;  75  }  76  }  77     if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);  78     return ws;  79 }  80 
 81 function Workbook() {  82     if (!(this instanceof Workbook)) return new Workbook();  83     this.SheetNames = [];  84     this.Sheets = {};  85 }  86 
 87 function s2ab(s) {  88     var buf = new ArrayBuffer(s.length);  89     var view = new Uint8Array(buf);  90     for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;  91     return buf;  92 }  93 
 94 export function export_table_to_excel(id) {  95     var theTable = document.getElementById(id);  96     console.log('a')  97     var oo = generateArray(theTable);  98     var ranges = oo[1];  99 
100     /* original data */
101     var data = oo[0]; 102     var ws_name = "SheetJS"; 103  console.log(data); 104 
105     var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); 106 
107     /* add ranges to worksheet */
108     // ws['!cols'] = ['apple', 'banan'];
109     ws['!merges'] = ranges; 110 
111     /* add worksheet to workbook */
112  wb.SheetNames.push(ws_name); 113     wb.Sheets[ws_name] = ws; 114 
115     var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'}); 116 
117     saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), "test.xlsx") 118 } 119 
120 function formatJson(jsonData) { 121  console.log(jsonData) 122 } 123 export function export_json_to_excel(th, jsonData, defaultTitle) { 124 
125     /* original data */
126 
127     var data = jsonData; 128  data.unshift(th); 129     var ws_name = "SheetJS"; 130 
131     var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); 132 
133 
134     /* add worksheet to workbook */
135  wb.SheetNames.push(ws_name); 136     wb.Sheets[ws_name] = ws; 137 
138     var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'}); 139     var title = defaultTitle || '列表'
140     saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), title + ".xlsx") 141 }

注意:在Export2Excel.js引入Blob.js時,目錄位置要對應

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM