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

需求说明 前端页面通过表格呈现查询数据,并由一个按钮点击事件将表格的数据以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; } 该函数流程大致为: 通过ID找到表格 利用XLSX的table_to_book方法将表格数据直接生成到工作簿 将工作簿包装为blob对象 通过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版本完全可行。 参考 SheetJS js-xlsx的git库 Element-ui组件库Table表格导出Excel表格 记element + xlsx 导出表格数据重复的坑

本文章由javascript技术分享原创和收集

发表评论 (审核通过后显示评论):