Vue+Element 实现excel的导入导出

vue

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时,目录位置要对应

 

以上是 Vue+Element 实现excel的导入导出 的全部内容, 来源链接: utcz.com/z/378975.html

回到顶部