需求:

在基于react+antd进行开发的页面中,实现导出excel报表的功能

实际场景:

1.简单数据:单层表头+数据

2.复杂数据:多层表头+数据

实现方式:

1.简单数据

简单数据的导出使用了js-export-excel插件,需要自己转换表头数据与表格数据,代码如下:

import { useState } from 'react';
import { message, Button } from 'antd';
import ExportJsonExcel from 'js-export-excel';
import type { RequestData } from '@/utils/request';
import type { ProjectInfoParams } from '@/services/summary';
import type { PaginationProps } from 'antd';
import { downloadChannelSettle } from '@/services/xxx'; // 接口地址 interface DownloadEffortsProps {
columnsData: any[];
totalList?: any[];
tableParams?: ProjectInfoParams & PaginationProps & { order?: string; sort?: string };
}
const DownloadEfforts: React.FC<DownloadEffortsProps> = (props) => {
const { columnsData, tableParams } = props; // 按钮loading
const [downLoading, setDownLoading] = useState<boolean>(false); // 下载结算申请报表
const downloadEffectExcel = async () => {
// 请求所有数据
const downloadParams = { ...tableParams, current: 1, pageSize: 0, pageNum: 1 };
// 开启按钮loading
setDownLoading(true);
try {
const res: RequestData = await downloadChannelSettle(downloadParams);
if (res.result) {
const { tableList } = res.result;
// 表头数组去掉操作栏
const newestHeaderList = columnsData.filter((arr: any) => arr.valueType !== 'option');
// 导出报表的表头与数据的处理
const resultData: any[] = [];
if (tableList) {
tableList.forEach((item: any, index: number) => {
const resultItem = {};
newestHeaderList.forEach((el: any, i: number) => {
if (newestHeaderList[i].title) {
resultItem[newestHeaderList[i].title] =
tableList[index][newestHeaderList[i].dataIndex];
}
});
resultData.push(resultItem);
});
}
const newHeader = newestHeaderList.map((item: any) => item.title);
const option = {
fileName: '导出数据', // 文件名字
datas: [
{
sheetData: resultData, // 数据
sheetName: 'sheet',
sheetFilter: newHeader, // 表头
sheetHeader: newHeader, // 表头
},
],
};
const toExcel = new ExportJsonExcel(option);
toExcel.saveExcel();
} else {
message.error('下载失败!');
}
} catch (error) {
//
} finally {
// 关闭按钮loading
setDownLoading(false);
}
}; return (
<Button key="downloadExcel" type="ghost" onClick={downloadEffectExcel} loading={downLoading}>
下载报表
</Button>
);
};
export default DownloadEfforts;

  

2.复杂数据

复杂数据,我只处理了多层表头的情况,table组件展示如图:

因为js-export-excel插件无法直接导出多层表头的数据(并且产品要求excel文件要与table展示布局相同),因此选用了react-html-table-to-excel插件进行开发,代码如下:

import { useState, useRef, useEffect } from 'react';
import { isEmpty } from 'lodash';
import { message, Table, Button } from 'antd';
import ReactHTMLTableToExcel from 'react-html-table-to-excel';
import type { RequestData } from '@/utils/request';
import type { ParamsType } from '@ant-design/pro-provider';
import type { PaginationProps } from 'antd';
import { downloadChannelGoBackReport } from '@/services/xxx';
import type { SettleApplicationParams } from '@/services/xxx'; interface DownloadEffortsProps {
columnsData: any[];
totalList?: any[];
tableParams?: ParamsType & PaginationProps & { order?: string; sort?: string; month?: string[] };
}
const DownloadEfforts: React.FC<DownloadEffortsProps> = (props) => {
const { columnsData, tableParams } = props;
const buttonRef = useRef<any>(null);
const tableRef = useRef<any>(null);
const [tableData, setTableData] = useState<SettleApplicationParams[]>([]); // 按钮loading
const [downLoading, setDownLoading] = useState<boolean>(false); // 下载报表
const downloadEffectExcel = async (e: any) => {
e.stopPropagation();
// 请求所有数据
const downloadParams = { ...tableParams, current: 1, pageSize: 0, pageNum: 1 };
if (downloadParams.month && !isEmpty(downloadParams.month)) {
// 开启按钮loading
setDownLoading(true);
try {
const res: RequestData = await downloadChannelGoBackReport(downloadParams);
if (res.result) {
const { tableList } = res.result;
setTableData(tableList);
} else {
message.error('下载失败!');
setDownLoading(false);
}
} catch (error) {
//
}
} else {
message.error('查询时间不能为空');
}
}; useEffect(() => {
// 拿到本次请求的数据后,再进行下载
if (columnsData.length > 0 && tableData.length > 0) {
const table = tableRef?.current?.querySelector('table');
table.setAttribute('id', 'table-to-xls');
buttonRef.current.handleDownload();
// 关闭按钮loading
setDownLoading(false);
// 下载完后,清除数据
setTimeout(() => {
setTableData([]);
}, 0);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [tableData]) useEffect(() => {
// 禁止组件按钮的默认点击事件(因为ts默认用的是Element,需要声明为HTMLElement)
const button = document.querySelector('#test-table-xls-button') as HTMLElement;
if (button) button.style['pointer-events'] = ('none');
}, []); return (<>
<Button key="downloadExcel" type="ghost" onClick={(e) => downloadEffectExcel(e)} loading={downLoading}>
下载报表
</Button>
<span style={{ visibility: 'hidden' }}>
<ReactHTMLTableToExcel
ref={buttonRef}
key="downloadExcel"
id="test-table-xls-button"
className="ant-btn"
table="table-to-xls"
filename="报表"
sheet="报表"
buttonText="下载报表"
/>
</span>
<div ref={tableRef} style={{ position: 'absolute', zIndex: -1, top: 0, left: 0, width: 0, height: 0 }}>
<Table
rowKey='id'
columns={columnsData.filter((arr: any) => arr.valueType !== 'option')}
dataSource={tableData}
/>
</div>
</>
);
};
export default DownloadEfforts;

  

最终导出效果:

【ps】:因为YYYY-MM格式的表头数据会在导出时自动转格式(如上图),因此可以在表头处理时手动转为【YYYY年MM月】的格式避免此类情况。

参考文档:https://blog.csdn.net/weixin_44240581/article/details/115265810

这两个依赖的配置项很接近,肉眼可以明确属性名的含义,不做赘述。

react+antd 导出excel文件(简单数据&多级表头)的更多相关文章

  1. POI导出大量数据的简单解决方案(附源码)-Java-POI导出大量数据,导出Excel文件,压缩ZIP(转载自iteye.com)

    说明:我的电脑 2.0CPU 2G内存 能够十秒钟导出 20W 条数据 ,12.8M的excel内容压缩后2.68M 我们知道在POI导出Excel时,数据量大了,很容易导致内存溢出.由于Excel ...

  2. java POI导出Excel文件数据库的数据

    在web开发中,有一个经典的功能,就是数据的导入导出.特别是数据的导出,在生产管理或者财务系统中用的非常普遍,因为这些系统经常要做一些报表打印的工作.这里我简单实现导出Excel文件. POI jar ...

  3. JavaScript 上万条数据 导出Excel文件(改装版)

    最近项目要js实现将数据导出excel文件,网上很多插件实现~~那个开心呀,谁知道后面数据量达到上万条时出问题:浏览器不仅卡死,导出的excel文件一直提示网络失败.... debug调试发现var  ...

  4. JavaScript 上万条数据 导出Excel文件 页面卡死

    最近项目要js实现将数据导出excel文件,网上很多插件实现~~那个开心呀,谁知道后面数据量达到上万条时出问题:浏览器不仅卡死,导出的excel文件一直提示网络失败.... debug调试发现var  ...

  5. 纯前端实现数据导出excel文件

    一  安装依赖 npm install -S file-saver xlsx npm install -D script-loader 二 新建文件夹 在网上百度引入即可 三 在main.js中引入 ...

  6. PHP导出excel文件,第一步先实现PHP模板导出不带数据

    今天继续研究PHP导出excel文件,把复杂的事情简单化,一步步实现功能,首先实现模板文件的导出,随后再实现写入数据后导出,最终实现功能,这是基本思路.中间可以加一步,先自己写入数据导出试试,随后再数 ...

  7. 前端必读3.0:如何在 Angular 中使用SpreadJS实现导入和导出 Excel 文件

    在之前的文章中,我们为大家分别详细介绍了在JavaScript.React中使用SpreadJS导入和导出Excel文件的方法,作为带给广大前端开发者的"三部曲",本文我们将为大家 ...

  8. PHPExcel导出excel文件

    今天园子刚开,先来个货顶下,后续园丁qing我会再慢慢种园子的,希望大家多来园子逛逛. PHPExcel导出excel文件,先说下重要的参数要记住的东西 impUser() 导入方法 exportEx ...

  9. asp.net 导出excel文件

    之前做过winfrom程序的导出excel文件的功能,感觉非常简单.现在试着做asp.net中导出excel的功能,之前用的是Microsoft.Office.Interop.Excel这个对象来实现 ...

  10. JQGrid导出Excel文件

    系列索引 Web jquery表格组件 JQGrid 的使用 - 从入门到精通 开篇及索引 Web jquery表格组件 JQGrid 的使用 - 4.JQGrid参数.ColModel API.事件 ...

随机推荐

  1. (0303)《计算机体系结构 量化研究方法》PDF

    (01) https://blog.csdn.net/konghhhhh/article/details/106828402  存储器相关 (1) https://blog.csdn.net/iva_ ...

  2. 采样定理与SDM

    1.信噪比=6.02N+1.76dB 对于这个经常引用的AD/DA转换器理论信噪比(SNR)公式,代表一个完美的N位ADC的理论性能.下面先计算N位模数转换器(ADC)的理论量化噪声.一旦通过计算均方 ...

  3. vscode 终端中运行执行js文件

    问题汇总 1.在vscode中执行node -v没有反应或者执行js文件出现下图错误 解决办法: 1.先关闭vscode,找到vscode的执行文件,在兼容性中勾上以管理员身份运行此程序,该问题win ...

  4. Java Swing 防止键入手Key 的实现方法

    实现思路,启动一个线程每隔0.1秒去比较文本里字符长度变化,如果文本变长了,这个情况间隔时间超过2秒,则认为是人工键入. 对于字符串较多,且包含数字和字母的情况,比较适用. class KeyCode ...

  5. 《TensorFlow+Keras自然语言处理实战》图书介绍

    #好书推荐##好书奇遇季#<TensorFlow+Keras自然语言处理实战>.当当京东天猫均有发售. https://item.jd.com/12788707.html 文后有本书配套源 ...

  6. 正则表达式re.compile()的使用

    re 模块提供了不少有用的函数,用以匹配字符串,比如: compile 函数match 函数search 函数findall 函数finditer 函数split 函数sub 函数subn 函数re ...

  7. 如何获取android环境自带的jar包

    首先找到你需要用到的类,Ctrl 并点击跳转到这个类 跳转过来之后,找到这个类所在的包 Ctrl并点击,此时会跳转到这个包所在的jar的位置 右键class.jar并选择在文件资源浏览器打开 打开以后 ...

  8. 吴恩达老师机器学习课程chapter07——聚类

    吴恩达老师机器学习课程chapter07--聚类 本文是非计算机专业新手的自学笔记,高手勿喷. 本文仅作速查备忘之用,对应吴恩达(AndrewNg)老师的机器学期课程第十三章. 缺少重要推演,只能作为 ...

  9. springboot1.x apollo 更改属性值不起作用。 ConfigurationProperties

    1. @ApolloConfigChangeListeners 默认监控命名空间是 application.properties , 如果是自己创建的namespace ,一定要明确指定(包含文件扩展 ...

  10. vvv动态组件和keep-alive

    <!DOCTYPE html><html> <head> <style> </style> <script src="a.j ...