前言
最近在开发一个数据展示的 Table页面需要增加一个Excel导出功能,用于运营人员做数据汇总。数据不算大,比较大的数据导出不建议前端实现(浏览器会崩), 但后端要求这个功能让前端来实现,故实现后记录这个方案
一些细节
由于是通过分页得到数据,这里通过后端的Total字段得到总数据量,后结合Promise,计算总共要获取的数据页数,获取所有数据后处理合并后进行导出。
Xlsx
这里使用sheetjs 这个库来实现核心的 xlsx文件导出, 对于导出它主要有以下几种方法:
Dom直接导出
import { utils, writeFileXLSX } from 'xlsx'
//raw 内容格式会被处理为纯文本 主要是为了防止出现乱码的情况
const wb = utils.table_to_book(Dom, { raw: true })
//需要 取当前年月日时分秒的数据
writeFileXLSX(wb, `报表.xlsx`)
对象或按数组结构写出
import { utils, writeFile } from 'xlsx'
let book = utils.book_new();
//对象形式写法 对象数组
// const sheet1 = utils.json_to_sheet([{ "id": "1", "ok": "123" }]);
//按行 二维数组
// const sheet2 = utils.aoa_to_sheet([["a", "b", "c"], [1, 2, 3]]);
const sheet2 = utils.aoa_to_sheet(data);
utils.book_append_sheet(book, sheet2, "异常工时登记");
writeFile(book, `异常工时登记报表${exportDateName}.xlsx`);
数据处理和导出
this.CurrentData = [];
//先计算当前 总条数是否大于100行
if (this.Total > this.MaxGetTotal) {
//取出总共要循环求几次数据
const num = Math.ceil(this.Total / this.MaxGetTotal);
const requestAry = []; //存储所有基于Promise封装的请求
for (let i = 1; i <= num; i++) {
requestAry.push(excelGetList(i, this.MaxGetTotal)); //传递Page Rows
}
//promise并发 to函数可以参考源码共读这一期内容噢https://juejin.cn/post/7138263385686147080
const [err, res] = await to(Promise.all(requestAry));
//拼接数据
res.forEach(
(item) =>
(this.CurrentData = this.CurrentData.concat(
item.data.Data
))
);
//不分页逻辑
} else {
// 不必分页那么 只拿一次数据就好
const [err, res] = await to(
excelGetList(1, this.MaxGetTotal)
);
this.CurrentData = res.data.Data
}
//...省略对于数据中对象和数组转换 以及一些判断
//创建一个空工作簿
const book = utils.book_new();
//创建一个工作表sheet 这里的main 就是你处理好的 二维数组或者对象数据
const sheet2 = utils.aoa_to_sheet(main);
//加入工作表到工作簿中
utils.book_append_sheet(book, sheet2, "工时登记");
writeFile(book, `工时登记报表.xlsx`);