需求:

在基于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. es实现规格动态域生成

    1.就是把sepc的可以提取出来作为一个域(sepc是一个规格参数) 封装搜索条件(跟jdbc流程一样) @requestparam( required = false) 的作用?   不传值后台也不 ...

  2. Quartz 2D实现文字镂空效果

    什么是镂空效果,下图就是一个镂空效果的文字: 从图可知,文字是透明的,可以看到下面的图片内容,而UILabel其它部分是白色背景. 使用Quartz 2D绘制镂空效果,大体思路如下: 实现一个UILa ...

  3. vue 项目中引入图片使用相对路径,图片不显示的问题

    在 vue 项目中引入图片,路径为相对路径时,会显示 src="[object Module]" 采用 import 方式引入图片,再设置到 src 中 会正常显示 file-lo ...

  4. springcloud(三) - 负载均衡Ribbon

    功能介绍 基本保证每个服务不同的ip接收到的请求数量是一样的,确保在微服务下没有没有那个服务器负载过多而另外一个闲置. IRule:根据规则获取制定的服务 规则列表 RoundRobinRule:轮询 ...

  5. Windows 10 与Windows11 功能比较(红字为不同点)

    Windows 10 与Windows11 功能比较(红字为不同点)

  6. VS编译运行报错:找不到ucrtbased.dll文件

    VS编译运行报错:找不到ucrtbased.dll文件 在VS2019中配置OpenCV编译,报如下错误: 解决方法:下载缺少的ucrtbased.dll文件,在免费的dll下载网站搜索下载,对应的有 ...

  7. yolov5学习遇到的困难

    本文观看目标检测 YOLOv5 开源代码项目调试与讲解实战[土堆 x 布尔艺数]_哔哩哔哩_bilibili视频来部署yolov5环境. 问题1:pycocotools工具包安装问题,参照视频2解决W ...

  8. 压缩打包,tar

    压缩打包命令 创建压缩包 tar -zcvf /home/xxxx.tar.gz /xahot 解压 tar -zxvf xxx.tar.gz gzip   xxxx  自动变为 xxx.gz

  9. python逐行读取替换文件中的字符串

    用列表中的值逐行替换文件中符合条件的字符串,并保存为新的文件, open("file").readlines 方案1: 逐行替换并保存为新的文件 import re def rep ...

  10. [*]Is L2 Physics-Informed Loss Always Suitable for Training Physics-Informed Neural Network?

    NeurIPS 2022 本篇工作对PINN中的物理损失进行了探究,作者认为L2损失并不总是适用于训练PINN.并从PDE解的稳定性角度给出了理论性的说明.读了这篇文章,感觉自己的毕业论文做的十分浅显 ...