4行代码实现vue + element ui的表格数据导出为xlsx文件

作者 : 开心源码 本文共2412个字,预计阅读时间需要7分钟 发布时间: 2022-05-13 共223人阅读

需求说明

前台页面通过表格呈现查询数据,并由一个按钮点击事件将表格的数据以xlsx的文件格式导出下载。

开发环境

Chrome + vue 2.0 + Element UI

方案1:XLSX + FILE-SAVER

因为文件下载需求的普遍性,以及vue和Element的流行性,网上相似的方案很多。稍作整理后的形式如下:

 // 导出按钮绑定的函数exportXLSX() {    // 从表格生成workbook    let wb = XLSX.utils.table_to_book(document.querySelector('#tableID'));    let wbout = XLSX.write(wb, {        bookType: "xlsx",        bookSST: true,        type: "array"    });    try {    // 下载        let b = new Blob([wbout], { type: "application/octet-stream" });        FileSaver.saveAs(b, "filename.xlsx");    } catch (e) {        if (typeof console !== "undefined") {            console.log(e, wbout);        }    }    return wbout;}

该函数流程大致为:

  1. 通过ID找到表格
  2. 利用XLSX的table_to_book方法将表格数据直接生成到工作簿
  3. 将工作簿包装为blob对象
  4. 通过FileSaver实现文件保存功能

问题1:可能导出重复数据

当使用Element UI的el-table中的fixed属性时,实际生成了2张表格,因而以上方案导出的数据会出现重复的现象。就像这样:

重复的数据

既然起因很清楚了,那么这个问题的处理办法也容易找到:在生成工作簿的时候,首先去除带有fix属性的表格,在工作簿对象生成后再增加上。
这样,生成工作簿的代码升级为:

let fix = document.querySelector('.el-table__fixed');if (fix) {    let wb = XLSX.utils.table_to_book(document.querySelector('#tableID').removeChild(fix));    document.querySelector('#tableID').appendChild(fix);} else {    let wb = XLSX.utils.table_to_book(document.querySelector('#tableID'));}

问题2:分页数据只导出页面显示的部分

假如表格存在分页,上述方法导出的是当前显示的部分。网上也有几种处理办法:

  • 前台隐藏一个全量的table,专门用于导出(个人不推荐)。
  • 导出的时候临时修改pageSize,使全量数据都在表格上。完成后复原。

这两个我都没尝试,也就不贴代码了,通过搜索都可以找到。

方案2:只使用XLSX处理问题

之前两个问题的处理办法要么触发了前台变更的操作,要么保存了多余的内容。尽管能处理问题,但总有些变扭。
重新看了看SheetJS项目的文档,发现有json_to_sheet方法,官方的示例如下:

var ws = XLSX.utils.json_to_sheet([  { S:1, h:2, e:3, e_1:4, t:5, J:6, S_1:7 },  { S:2, h:3, e:4, e_1:5, t:6, J:7, S_1:8 }], {header:["S","h","e","e_1","t","J","S_1"]});

假如不显式定义列名,则以第一个对象的Object.keys作为列名。

The default column order is determined by the first appearance of the field using Object.keys

这不正和el-table的表单数据格式一模一样么。本地已经有tableData,且是全量数据,不存在分页问题,直接用tableData加上json_to_sheet方法生成sheet便可。但这个方法返回的是worksheet,而非workbook,因而需要增加到一个workbook。最后使用workbook的writeFile方法就可完成下载。最终代码如下:

exportXLSX() {        let ws = XLSX.utils.json_to_sheet(this.tableData);        let wb = XLSX.utils.book_new();        XLSX.utils.book_append_sheet(wb, ws, 'sheetname');        return XLSX.writeFile(wb, 'filename.xlsx');    }

代码可以如此简洁,且用不着file-saver的起因是,其实writeFile方法包装了很多行为,包括使浏览器生成文件的链接并强制点击,触发文件保存的动作等。

XLSX.writeFile wraps a few techniques for triggering a file save:

  • URL browser API creates an object URL for the file, which the library uses by creating a link and forcing a click. It is supported in modern browsers.
  • msSaveBlob is an IE10+ API for triggering a file save.
  • IE_FileSave uses VBScript and ActiveX to write a file in IE6+ for Windows XP and Windows 7. The shim must be included in the containing HTML page.

不知道这样的兼容性如何,至少Chrome 80版本完全可行。

参考

  1. SheetJS js-xlsx的git库
  2. Element-ui组件库Table表格导出Excel表格
  3. 记element + xlsx 导出表格数据重复的坑
说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 4行代码实现vue + element ui的表格数据导出为xlsx文件

发表回复