软件定制开发供应商vue:前端json数据 导出excel(Export2Excel)

一、背景:

软件定制开发供应商导出的功能,软件定制开发供应商通常后端处理好,前端直接通过地址进行下载即可,能不能是前端直接自己导出json文件,形成excel呢,当然可以。

二、实现步骤:

2.1、安装三个插件,分别是:、 xlsx、script-loader

npm install -S file-saver xlsx

npm install -D script-loader

2.2、utils目录下创建文件

2.3、Export2Excel.js

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

2.3、Blob.js

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

2.4、业务代码测试:

  1. // 引入Export2Excel
  2. const {export_json_to_excel} = require('../../utils/Export2Excel');
  3. // json数据-导出Excel
  4. exportToExcel() {
  5. require.ensure([], () => {
  6. const tHeader = ['字段1', '字段2', '字段3', '字段4', '字段5'];
  7. const filterVal = ['name1', 'name2', 'name3', 'name4', 'name5'];
  8. this.listQuery.limit = 9999
  9. // 调用接口,获取数据
  10. getJsonList(this.listQuery).then(response => {
  11. if(response.code == 200){
  12. const exceldata = this.formatJson(filterVal, response.data.records);
  13. export_json_to_excel(tHeader, exceldata, '西药列表');  //对应下载文件的名字
  14. }
  15. });
  16. })
  17. },

经过测试下载成功,打开后内容显示正确,可放心使用。

三、欢迎交流指正,关注我,一起学习。

四、参考链接:

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发