react+antd 导出excel文件(简单数据&多级表头)
需求:
在基于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文件(简单数据&多级表头)的更多相关文章
- POI导出大量数据的简单解决方案(附源码)-Java-POI导出大量数据,导出Excel文件,压缩ZIP(转载自iteye.com)
说明:我的电脑 2.0CPU 2G内存 能够十秒钟导出 20W 条数据 ,12.8M的excel内容压缩后2.68M 我们知道在POI导出Excel时,数据量大了,很容易导致内存溢出.由于Excel ...
- java POI导出Excel文件数据库的数据
在web开发中,有一个经典的功能,就是数据的导入导出.特别是数据的导出,在生产管理或者财务系统中用的非常普遍,因为这些系统经常要做一些报表打印的工作.这里我简单实现导出Excel文件. POI jar ...
- JavaScript 上万条数据 导出Excel文件(改装版)
最近项目要js实现将数据导出excel文件,网上很多插件实现~~那个开心呀,谁知道后面数据量达到上万条时出问题:浏览器不仅卡死,导出的excel文件一直提示网络失败.... debug调试发现var ...
- JavaScript 上万条数据 导出Excel文件 页面卡死
最近项目要js实现将数据导出excel文件,网上很多插件实现~~那个开心呀,谁知道后面数据量达到上万条时出问题:浏览器不仅卡死,导出的excel文件一直提示网络失败.... debug调试发现var ...
- 纯前端实现数据导出excel文件
一 安装依赖 npm install -S file-saver xlsx npm install -D script-loader 二 新建文件夹 在网上百度引入即可 三 在main.js中引入 ...
- PHP导出excel文件,第一步先实现PHP模板导出不带数据
今天继续研究PHP导出excel文件,把复杂的事情简单化,一步步实现功能,首先实现模板文件的导出,随后再实现写入数据后导出,最终实现功能,这是基本思路.中间可以加一步,先自己写入数据导出试试,随后再数 ...
- 前端必读3.0:如何在 Angular 中使用SpreadJS实现导入和导出 Excel 文件
在之前的文章中,我们为大家分别详细介绍了在JavaScript.React中使用SpreadJS导入和导出Excel文件的方法,作为带给广大前端开发者的"三部曲",本文我们将为大家 ...
- PHPExcel导出excel文件
今天园子刚开,先来个货顶下,后续园丁qing我会再慢慢种园子的,希望大家多来园子逛逛. PHPExcel导出excel文件,先说下重要的参数要记住的东西 impUser() 导入方法 exportEx ...
- asp.net 导出excel文件
之前做过winfrom程序的导出excel文件的功能,感觉非常简单.现在试着做asp.net中导出excel的功能,之前用的是Microsoft.Office.Interop.Excel这个对象来实现 ...
- JQGrid导出Excel文件
系列索引 Web jquery表格组件 JQGrid 的使用 - 从入门到精通 开篇及索引 Web jquery表格组件 JQGrid 的使用 - 4.JQGrid参数.ColModel API.事件 ...
随机推荐
- Quartz 2D CGPattern学习笔记
CGPattern是在图形上下文中重复绘制的一系列绘制操作.你可以像使用颜色一样使用图案.当使用CGPattern进行绘制时,Quartz将页面划分为一组图案单元格,每个单元格的大小为CGPatter ...
- Gtiee_上传本地项目
Git_本地代码上传到码云 本文仅作学习记录,方便日后翻看 创建本地仓库 找到自己本地代码的文件夹,打开Git GUI Here,输入git init创建本地仓库,当前文件夹下有.git文件表示创建成 ...
- JAVA学习笔记-09
多线程: 进程:就是正在执行中的程序,每一个进程执行都有一个执行的顺序,该顺序是一个执行路径.或者叫一个控制单元. 线程:就是进程中的一个独立的控制单元,线程在控制着进程的执行 一个进程中至少有一个线 ...
- docker中搭建Ubuntu:16.04+python3.6+django环境
用vim 新建一个Dockerfile和sources.list文件,在里面添加如下内容. #sources.list deb http://mirrors.163.com/ubuntu/ xenia ...
- 2022-11-19学习内容-Server端代码编写-Client端代码编写
1.Server端代码编写 1.1UserDBHelper.java package com.example.chapter07_server.database; import android.con ...
- jmeter使用Java请求二
继承 AbstractJavaSamplerClient类来实现jar编辑 来写jmeter测试脚本 将如下两个包引入Java项目: ApacheJMeter_core.jar ApacheJMete ...
- 遍历List时删除元素导致List抛出java.util.ConcurrentModificationException异常
1 public static void main(String[] args) { 2 List<String> list = new ArrayList<String>() ...
- J V M(二)双亲委派机制及native
package java.lang;public class String {// 双亲委派机制: 安全// 应用程序加载器-扩展程序加载器-根加载器// 自底向上检查类是否被加载,自顶向下加载类// ...
- 把本地项目上传到github
一在本地项目文件内,git初始化,并add, commit cd /test/xxxdemo git init add . commit -m "inits" 二在github创建 ...
- centos 服务器配置网络ifconfig位置
path : /etc/sysconfig/network-scripts/ifcfg-enoxxx