使用XLSX和FileSaver,纯前端实现导出大批量数据,并生成excel

2,206

因为项目中涉及到excel导出,以前的开发方式是请求接口,后端返回一个流,前端把流转化为excel,并下载,现在不是这套流程,是纯前端自己做的,实现的思路是,假如一共有500条数据,每次请求50次,一共请求10次,第10次请求结束后,生成excel,并导出(前端所用框架是vue,写法是按照vue的写法实现的),加上promise去实现。

1.安装插件

npm install XLSX

npm install FileSaver

因为多个页面都会用到导出excel功能,所以把封装一下方法,实现复用

import XLSX from "xlsx";
import FileSaver from 'file-saver'
export function excelData (id,name) {
  let xlsxParam = { raw: true } 
  let wb = XLSX.utils.table_to_book(document.querySelector(`#${id}`), xlsxParam)
  let wbout = XLSX.write(wb, { bookType: 'xlsx', bookSST: true, type: 'array' })
  try {
    FileSaver.saveAs(new Blob([wbout], { type: 'application/octet-stream' }), `${name}.xlsx`)
  } catch (e) {
    if (typeof console !== 'undefined') {
      console.log(e, wbout)
    }
  }
  return wbout
}

在组件中使用 import { excelData } from "@/excel.js"

在template里


<el-button type="primary"  @click="exportData" size="small">导出数据</el-button>
<el-table
      :data="tableDataAll"
      id="exportId"
      style="display:none;"
    >
    ...省去表格的内容
</el-table>

data里定义数据

tableDataAll :[],//表格数据
tableDateTotal :[],//表格数据总条数
queryData :{  //查询条件
    page:1,
    size:10
}

这里面el-table不展示在页面,只作为导出excel使用,具体可以网上查看FileSaver这个的具体实现

 exportData(){
    this.tableDataAll = [];
      let p = new Promise((resolve, reject)=> {
        resolve();
      });
    //这个是获取一共有多少条,每次请求50条数据,一共请求多少次
    let { tableDateTotal } = this.$data;
      let num = 1;
      if (tableDateTotal % 50 == 0) {
        num = parseInt(tableDateTotal / 50)
      }else{
        num = parseInt(tableDateTotal / 50) + 1;
      }
      for (let i = 1; i <= num; i++) {
        //i是每次请求的第几页
         p = p.then(this.get_request_sth_func(i));
      }
      p.then(()=> {
         //第一个参数,通过id去找到表格,相当去把table内容挪到excel里,第二个参数表示导出后excel的名称
         excelData("exportId","课程观看数据")
        setTimeout(()=>{
            //导出完excel后清空这个表格,避免页面dom结构过大,毕竟也是几百条,几千条数据呢,换算成dom不少呢
            this.tableDataAll=[];
        },200)
      });
}  

get_request_sth_func(i) {
      return () => {
        return new Promise((resolve, reject) => {
          let { queryData } = this.$data;
          queryData.page = i;
          delete queryData.size;
          this.$axios.get("请求地址", { ...queryData, size: 50 }).then(res => {
            this.tableDataAll.push(...res.list);
            resolve();
          });
        });
      };
    },

注意一下,XLSX和FileSaver导出原理,是把页面上的table转成excel的,所以这个重点就是利用promise实现把所有的数据下完成后在页面渲染成完整的table,再去实现导出。