今天研究一下前端如何导出excel,边查边实践,边记录

1.安装依赖库

xlsx:这是一个功能强大的excel处理库,但是上手难度也很大,还涉及不少二进制的东西

file-saver:ES5新增了相关file,blob,fileList等API,但不是所有浏览器都支持,file-saver在没有原生支持saveAs的浏览器上实现了saveAs()接口

script-loader: 在全局上下文环境中执行一次js脚本。

  1. npm install -D xlsx file-saver
  2. npm install -s script-loader

二、引入相关依赖(第二步可以忽略,)

上述部分依赖不支持import引入,所以需要使用'script-loader'将他们挂载到全局环境下;

其中的blob.js是github上的一个开源文件,对于浏览器不能原生支持blob的情况,提供了兼容解决方案,其地址是:https://github.com/eligrey/Blob.js

script-loader使用方法:

  1. require('script-loader!file-saver'); //保存文件用
  2. require('script-loader!vendor/Blob'); //转二进制用
  3. require('script-loader!xlsx/dist/xlsx.core.min'); //xlsx核心

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));

Blob,js

三、封装Export2Excel.js,它对外暴露两个接口:export_table_to_excelexport_json_to_excel(我是在src下的vendor文件夹放的这个js)

Export2Excel.js:

  1. /* eslint-disable */
  2. require('script-loader!file-saver');
  3. import XLSX from 'xlsx'
  4.  
  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({
  32. s: {
  33. r: R,
  34. c: outRow.length
  35. },
  36. e: {
  37. r: R + rowspan - 1,
  38. c: outRow.length + colspan - 1
  39. }
  40. });
  41. };
  42.  
  43. //Handle Value
  44. outRow.push(cellValue !== "" ? cellValue : null);
  45.  
  46. //Handle Colspan
  47. if (colspan)
  48. for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
  49. }
  50. out.push(outRow);
  51. }
  52. return [out, ranges];
  53. };
  54.  
  55. function datenum(v, date1904) {
  56. if (date1904) v += 1462;
  57. var epoch = Date.parse(v);
  58. return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
  59. }
  60.  
  61. function sheet_from_array_of_arrays(data, opts) {
  62. var ws = {};
  63. var range = {
  64. s: {
  65. c: 10000000,
  66. r: 10000000
  67. },
  68. e: {
  69. c: 0,
  70. r: 0
  71. }
  72. };
  73. for (var R = 0; R != data.length; ++R) {
  74. for (var C = 0; C != data[R].length; ++C) {
  75. if (range.s.r > R) range.s.r = R;
  76. if (range.s.c > C) range.s.c = C;
  77. if (range.e.r < R) range.e.r = R;
  78. if (range.e.c < C) range.e.c = C;
  79. var cell = {
  80. v: data[R][C]
  81. };
  82. if (cell.v == null) continue;
  83. var cell_ref = XLSX.utils.encode_cell({
  84. c: C,
  85. r: R
  86. });
  87.  
  88. if (typeof cell.v === 'number') cell.t = 'n';
  89. else if (typeof cell.v === 'boolean') cell.t = 'b';
  90. else if (cell.v instanceof Date) {
  91. cell.t = 'n';
  92. cell.z = XLSX.SSF._table[14];
  93. cell.v = datenum(cell.v);
  94. } else cell.t = 's';
  95.  
  96. ws[cell_ref] = cell;
  97. }
  98. }
  99. if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
  100. return ws;
  101. }
  102.  
  103. function Workbook() {
  104. if (!(this instanceof Workbook)) return new Workbook();
  105. this.SheetNames = [];
  106. this.Sheets = {};
  107. }
  108.  
  109. function s2ab(s) {
  110. var buf = new ArrayBuffer(s.length);
  111. var view = new Uint8Array(buf);
  112. for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
  113. return buf;
  114. }
  115.  
  116. export function export_table_to_excel(id) {
  117. var theTable = document.getElementById(id);
  118. var oo = generateArray(theTable);
  119. var ranges = oo[1];
  120.  
  121. /* original data */
  122. var data = oo[0];
  123. var ws_name = "SheetJS";
  124.  
  125. var wb = new Workbook(),
  126. ws = sheet_from_array_of_arrays(data);
  127.  
  128. /* add ranges to worksheet */
  129. // ws['!cols'] = ['apple', 'banan'];
  130. ws['!merges'] = ranges;
  131.  
  132. /* add worksheet to workbook */
  133. wb.SheetNames.push(ws_name);
  134. wb.Sheets[ws_name] = ws;
  135.  
  136. var wbout = XLSX.write(wb, {
  137. bookType: 'xlsx',
  138. bookSST: false,
  139. type: 'binary'
  140. });
  141.  
  142. saveAs(new Blob([s2ab(wbout)], {
  143. type: "application/octet-stream"
  144. }), "test.xlsx")
  145. }
  146.  
  147. export function export_json_to_excel({
  148. multiHeader = [],
  149. header,
  150. data,
  151. filename,
  152. merges = [],
  153. autoWidth = true,
  154. bookType= 'xlsx'
  155. } = {}) {
  156. /* original data */
  157. filename = filename || 'excel-list'
  158. data = [...data]
  159. data.unshift(header);
  160.  
  161. for (let i = multiHeader.length-1; i > -1; i--) {
  162. data.unshift(multiHeader[i])
  163. }
  164.  
  165. var ws_name = "SheetJS";
  166. var wb = new Workbook(),
  167. ws = sheet_from_array_of_arrays(data);
  168.  
  169. if (merges.length > 0) {
  170. if (!ws['!merges']) ws['!merges'] = [];
  171. merges.forEach(item => {
  172. ws['!merges'].push(XLSX.utils.decode_range(item))
  173. })
  174. }
  175.  
  176. if (autoWidth) {
  177. /*设置worksheet每列的最大宽度*/
  178. const colWidth = data.map(row => row.map(val => {
  179. /*先判断是否为null/undefined*/
  180. if (val == null) {
  181. return {
  182. 'wch': 10
  183. };
  184. }
  185. /*再判断是否为中文*/
  186. else if (val.toString().charCodeAt(0) > 255) {
  187. return {
  188. 'wch': val.toString().length * 2
  189. };
  190. } else {
  191. return {
  192. 'wch': val.toString().length
  193. };
  194. }
  195. }))
  196. /*以第一行为初始值*/
  197. let result = colWidth[0];
  198. for (let i = 1; i < colWidth.length; i++) {
  199. for (let j = 0; j < colWidth[i].length; j++) {
  200. if (result[j]['wch'] < colWidth[i][j]['wch']) {
  201. result[j]['wch'] = colWidth[i][j]['wch'];
  202. }
  203. }
  204. }
  205. ws['!cols'] = result;
  206. }
  207.  
  208. /* add worksheet to workbook */
  209. wb.SheetNames.push(ws_name);
  210. wb.Sheets[ws_name] = ws;
  211.  
  212. var wbout = XLSX.write(wb, {
  213. bookType: bookType,
  214. bookSST: false,
  215. type: 'binary'
  216. });
  217. saveAs(new Blob([s2ab(wbout)], {
  218. type: "application/octet-stream"
  219. }), `${filename}.${bookType}`);
  220. }

调用:

这里只调用了将json数据导出成excel表格:

template:

  1. <el-button type="primary" @click="handleDownload">导出excel</el-button>

data:

  1. tableData: [{
  2. date: '2016-05-02',
  3. name: '王小虎',
  4. address: '上海市普陀区金沙江路 1518 弄'
  5. }, {
  6. date: '2016-05-04',
  7. name: '王小虎',
  8. address: '上海市普陀区金沙江路 1517 弄'
  9. }, {
  10. date: '2016-05-01',
  11. name: '王小虎',
  12. address: '上海市普陀区金沙江路 1519 弄'
  13. }, {
  14. date: '2016-05-03',
  15. name: '王小虎',
  16. address: '上海市普陀区金沙江路 1516 弄'
  17. }]
methods:
  1. handleDownload(){
  2. var self=this;
  3. import('@/vendor/Export2Excel').then(excel=>{
  4. console.log(excel);
  5. const tHeader = ['日期', '姓名', '地址']
  6. const filterVal = ['date', 'name', 'address']
  7. const list = self.tableData
  8. const data = self.formatJson(filterVal, list)
  9.  
  10. excel.export_json_to_excel({
  11. header: tHeader,//表头
  12. data,//json数据
  13. filename: "excel导出测试",//导出文件名
  14. autoWidth: true,//宽度是否自适应
  15. bookType: "xlsx",//导出文件后缀名
  16. })
  17. })
  18. },
  19. formatJson(filterVal, jsonData) {//将时间戳转化为日期格式yyyy-mm-dd(如果json中没有timestamp属性,则无效)
  20. return jsonData.map(v => filterVal.map(j => {
  21. if (j === 'timestamp') {
  22. return parseTime(v[j])
  23. } else {
  24. return v[j]
  25. }
  26. }))
  27. }

导出效果

 

vue项目,前端导出excel的更多相关文章

  1. vue 纯前端导出 excel 表格

    在开发后台管理系统的时候,很多地方都要用到导出excel 表格,比如将table中的数据导出到本地,那么实现这种需求往往有两种方案: 一.后端开发一个下载链接,前端将这个链接放到 a 标签的 href ...

  2. vue项目前端导出word文件(bug解决)

    摘要:之前项目中导出价格表是由后端实现,前端只需要调用接口下载word即可,后来业务改变比较大,word模版需要一直改动,后端改起来相对麻烦,后来直接前端自己定义模版,实现下载word文档. 一.需要 ...

  3. vue项目中导出Excel文件功能的前端代码实现

    在项目中遇到了两种不同情况, 1.get请求导出文件,实现起来相对简单 // 导出数据 exportData() { window.location.href = `/oes-content-mana ...

  4. vue实现前端导出excel表格

    1.在src目录下创建一个文件(vendor)进入Blob.js和Export2Excel.js 2.npm install -S file-saver 用来生成文件的web应用程序 3.npm in ...

  5. 前端导出Excel兼容写法

    今天整理出在Web前端导出Excel的写法,写了一个工具类,对各个浏览器进行了兼容. 首先,导出的数据来源可能有两种: 1. 页面的HTML内容(一般是table) 2. 纯数据 PS:不同的数据源, ...

  6. 前端导出excel表

    前端导出excel表 方式一: 前端js实现 : https://www.cnblogs.com/zhangym118/p/6235801.html 方式二: java后端实现: https://bl ...

  7. 前端导出Excel

    1.首先,需要下载一个叫better-xlsx,的插件,以yarn 为例 ' yarn add better-xlsx --save '下载相关依赖包( npm 方式 ' npm i better-x ...

  8. js前端导出excel

    此例子是利用html特性,纯前端导出excel,样式不好看,兼容主流浏览器. var tableid = jQuery(this).closest("div.tab-label-wrap&q ...

  9. 踹掉后端,前端导出Excel!

    前言 导出Excel文件这个功能,通常都是在后端实现返回前端一个下载链接,但有时候我们只想导出前端页面上已经有了的数据,不想再调后端导出接口浪费服务器资源,学习本文demo例子,我们踹掉后端,直接在前 ...

随机推荐

  1. Linux中 ls -l 命令显示结果中的每一列的含义

    图片转载自:https://blog.csdn.net/zhuoya_/article/details/77418413 简单解释下: 1.第一列颜色框:文件类型列,这里简单描述几种常见类型,d表示目 ...

  2. hdu 2844 多重背包的转化问题 以及这个dp状态的确定

    在杭电上测试了下 这里的状态转移方程有两个.,. 现在有价值val[1],val[2],…val[n]的n种硬币, 它们的数量分别为num[i]个. 然后给你一个m, 问你区间[1,m]内的所有数目, ...

  3. CCF 201809-1 卖菜

    题目: 问题描述 在一条街上有n个卖菜的商店,按1至n的顺序排成一排,这些商店都卖一种蔬菜. 第一天,每个商店都自己定了一个价格.店主们希望自己的菜价和其他商店的一致,第二天,每一家商店都会根据他自己 ...

  4. C#强制回收垃圾

    [DllImport("psapi.dll")] private static extern int EmptyWorkingSet(int hProcess); public v ...

  5. restTemplate源码解析(二)restTemplate的核心逻辑

    所有文章 https://www.cnblogs.com/lay2017/p/11740855.html 正文 上一篇文章中,我们构造了一个RestTemplate的Bean实例对象.本文将主要了解一 ...

  6. 对SPI进行参数化结构设计

    前言 为了避免每次SPI驱动重写,直接参数化,尽量一劳永逸. SPI master有啥用呢,你发现各种外围芯片的配置一般都是通过SPI配置的,只不过有3线和四线. SPI slave有啥用呢,当外部主 ...

  7. 【Hibernate】 二级缓存及查询缓存

    一.Hibernate的二级缓存 1.1 类缓存区特点 缓存的是对象的散装的数据. 图一 Hibernate的二级缓存的散装数据 1.2 集合缓存区的特点: 缓存的是对象的id.需要依赖类缓冲区的配置 ...

  8. Java学习第三天之注释

    编写程序时,总需要为程序添加一些注释,用以说明某段代码的作用,或者说明某个类的用途.某个方法的功能,以及该方法的参数和返回值的数据类型及意义等. 一.为什么要添加注释? (1)便于自己理解:有些人可能 ...

  9. 华擎 J3455 主板装 Linux 系统

    入手华擎J3455 ITX 主板,装备安装一个 redhat 来学习linux,及做一个家庭 web 服务器.但安装过程一波三折. 问题1.使用U盘引导不了,首先华擎这块板是 UEFI 板,用之前的老 ...

  10. MacOS下安装unicorn这个库失败

    因为在Mac下安装pwntools,发现安装unicorn库的时候失败了,编译报错如下 make: *** [qemu/config-host.h-timestamp] Error 1 error: ...