Table之多分页Excel导出


一、背景

在现代项目开发中,众所周知,对于excel的文件一般由后端开发人员做下载导出链接,进行导出功能的实现。而最近我在工作中遇到了这样的问题,就是表格的数据统计依赖总公司的综合数据,且数据类目庞大,因此后端查询接口在尽力优化下,每个接口也将近30s的反应时间,这对于用户来说是不友好的。而且页面呈现的数据报表已经等待了几十秒加载出来,如果在导出的时候还需要在进行等待重新访问接口,势必是对用户体验不太好。所以我决定通过前端来导出这些已经拿到的table数据。这样就可以节省二次访问时间啦~

二、依赖及解决的问题

依赖:element-ui-table + file-saver + xlsx
在项目中因为考虑到快速开发迭代的节奏,我们选用了Element-UI的Table组件。但是在导出excel的同时,也遇到了一些棘手的问题。

三、解决的问题

  1. 因为table组件中用到了fixed的属性,在过长的表格,用于对核心的数据列或数据表头进行固定。但是因为fixed的属性,在进行导出的时候会导出两个table。因为我们探究一下就可以发现,当table组件使用了fixed的属性时,对于固定单元和非固定单元是进行了不同table的拼接,因此我们在进行excel导出的时候要进行处理。
    具体的处理方法是:在要导出时,先保存fixed的固定dom节点,然后删除它,进行数据导出以后,在进行append就好啦。
  2. 第二个问题是:在导出excel的时候,我们都知道,有sheet的分类,正常情况下是默认一个sheet的。但是如何在一个excel中导出含有多个sheet的文件呢。
    具体的处理方法是:这个时候就要用到 XLSX.utils.table_to_sheet()这个方法进行多sheet的拼接。
  3. 第三个问题是:导出的excel中如果是百分比的数据,导出的格式就是字符串形式,但是excel会有黄色的警告。其实对于这个问题也有解决。
    具体的处理方法是:就是通过声明let xlsxParam = { raw: true } // 导出的内容只做解析,不进行格式转换。但是导出的时候确实数字了,不过就没有百分比的形式啦。举例:'80%' => 0.8 因此,这里我建议大家还是只做解析,不进行格式转换。
  4. 第四个问题就是对于excel的导出的兼容性和速度的取舍,涉及到这样一个属性bookSST: true。当bookSST为false就相应的降低了兼容性,但同时也提高了导出生成表格的速度。这里我考虑的是兼容性,因此我设置为true了。
/*
 * @Author: xuhao 
 * @Date: 2020-05-28 17:02:39 
 * @description: Table数据导出为excel文件,该导出为前端导出,依赖现有数据,少一次请求(部分请求最高达30s),节省用户等待时间。
 * @Last Modified by: xuhao
 * @Last Modified time: 2020-07-09 11:24:42
 */

//引入依赖
import FileSaver from 'file-saver';
import XLSX from 'xlsx';

// id为table的标示,title为table名称
export const exportExcel = (id, title) => {
  let ids, wbout;
  // 判断是否是含多sheet的excel
  if (id.includes(',')) { // 含多sheet的excel
    ids = JSON.parse(id)
    let workbook = XLSX.utils.book_new();
    let xlsxParam = { raw: true } // 导出的内容只做解析,不进行格式转换
    ids.forEach((item, index) => {
      let tableDom = document.querySelector(`#${item.key}`)
      let fix = document.querySelector(`#${item.key} .el-table__fixed`);
      if (fix) { // 如果存在固定列,防止导出的excel表格会重复两遍
        // workbook = XLSX.utils.table_to_sheet(dom, xlsxParam);
        XLSX.utils.book_append_sheet(workbook, XLSX.utils.table_to_sheet(tableDom.removeChild(fix), xlsxParam), item.name);
        tableDom.appendChild(fix)
      } else {
        XLSX.utils.book_append_sheet(workbook, XLSX.utils.table_to_sheet(document.querySelector(`#${item.key}`), xlsxParam), item.name);
      }
    })
    // bookSST 开启之后会降低导出速率,但是会提高兼容性
    wbout = XLSX.write(workbook, { bookType: 'xlsx', bookSST: true, type: 'array' });
  } else { // 单个默认sheet的excel
    ids = id
    /* generate workbook object from table */
    //  判断要导出的节点中是否有fixed属性(即,固定列)的表格,如果有,转换excel时先将该dom移除,然后append回去
    let fix = document.querySelector(`#${ids} .el-table__fixed`);
    let workbook;
    let xlsxParam = { raw: true } // 导出的内容只做解析,不进行格式转换
    if (fix) { // 如果存在固定列,防止导出的excel表格会重复两遍
      let dom = document.querySelector(`#${ids}`).removeChild(fix)
      workbook = XLSX.utils.table_to_book(dom, xlsxParam)
      document.querySelector(`#${ids}`).appendChild(fix)
    } else {
      workbook = XLSX.utils.table_to_book(document.querySelector(`#${ids}`), xlsxParam);
    }
    // bookSST 开启之后会降低导出速率,但是会提高兼容性
    wbout = XLSX.write(workbook, { bookType: 'xlsx', bookSST: true, type: 'array' });
  }
  /* get binary string as output */
  try {
    FileSaver.saveAs(new Blob([wbout], { type: 'application/octet-stream' }), title)
  } catch (e) {
    if (typeof console !== 'undefined') {
      console.log(e, wbout)
    }
  }
  return wbout
};

声明:Xuhao's Blog|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - Table之多分页Excel导出


Carpe Diem and Do what I like