react + xlsx 表格导出功能 全部实现

需求 : 在react中将表格多样化导出 , 既可以全部导出所有表格数据 , 也可以选择性导出 + 导出可以选择三种样式

 




选择了全部 , 不能选其他 



全部导出



部分导出



1 导出按钮下拉弹出三种导出格式

           <Dropdownmenu={{items: [{label: (<aonClick={() => {setFormat('xlsx')}}>导出Excel</a>),key: '1'},{label: (<aonClick={() => {setFormat('csv')}}>导出CSV</a>),key: '2'},{label: (<aonClick={() => {setFormat('txt')}}>导出TXT</a>),key: '3'}]}}><Buttontype='primary'ghosticon={<imgsrc={derive}alt=''style={{ width: 11, height: 10, pointerEvents: 'none' }}/>}style={{ width: 125, height: 40, fontSize: 16 }}>导出</Button></Dropdown>

2 多选框内选中全部时 , 其他不被选中 ; 选中其他时 , 全部不被选中
 

// Checkbox.Group不必被盒子包裹 , 而Radio.Group必须得被盒子包裹<Checkbox.Group value={value2} onChange={value2Change}><Checkbox style={{ marginTop: 20, marginRight: 15 }} value={1}>全部</Checkbox><Checkboxstyle={{ marginTop: 20, marginRight: 15 }}value={'工单编号'}>工单编号</Checkbox><Checkboxstyle={{ marginTop: 20, marginRight: 15 }}value={'地点'}>地点</Checkbox><Checkboxstyle={{ marginTop: 20, marginRight: 15 }}value={'位置'}>位置</Checkbox><Checkboxstyle={{ marginTop: 20, marginRight: 15 }}value={'设备类型'}>设备类型</Checkbox><Checkboxstyle={{ marginTop: 20, marginRight: 15 }}value={'品牌/型号'}>品牌/型号</Checkbox><Checkboxstyle={{ marginTop: 20, marginRight: 15 }}value={'设备编号'}>设备编号</Checkbox><Checkboxstyle={{ marginTop: 20, marginRight: 15 }}value={'报修单状态'}>报修单状态</Checkbox></Checkbox.Group>const [value2, setValue2] = useState([1])const value2Change = checkedValues => {if (checkedValues.includes(1)) {// 如果"全部"被选中,则清除所有其他选项,仅保留"全部"if (checkedValues.length > 1) {// 如果还有其他选项被选中,则清空数组,仅保留"全部"setValue2([1])} else {// 如果只有"全部"被选中,保持现状setValue2(checkedValues)}} else {// 如果"全部"未被选中,且当前有其他选项被选中,则直接更新状态// 注意:这里确保了当选择其他任何选项时,"全部"不会被选中setValue2(checkedValues.filter(value => value !== 1))}}// 拿到实时的value2useEffect(() => {console.log('value2', value2)}, [value2])

3 导出的具体实现


3.1 data中定义了数据结构 , column是表格列的数据 , 我需要将data中列的数据转成column中title的值

流程图如下

  const [data, setData] = useState([{key: '1',username: 'B123',realname: '北京总部大厦',sex: '三层会议室',birthday: '打印机',phone: 'AB-0312',orgCodeTxt: 'AB0312',status: 1,action: 1},
...
] const columns0 = [{title: <span onClick={() => handleSort('username')}>工单编号</span>,dataIndex: 'username',align: 'center',key: 'username'},
...
] // 遍历columns0,为data中的每个对象创建一个仅含转换后数据的新对象let data1 = data.map(item => {const newItem = {}columns0.forEach(column => {const title = getTitleText(column)const dataIndex = column.dataIndexif (title && item.hasOwnProperty(dataIndex)) {// 对于'status'列,直接应用状态码转换逻辑newItem[title] =column.dataIndex === 'status'? getStatusText(item[dataIndex]): item[dataIndex]}})return newItem})console.log('data1', data1)
// 这样打印出data1的值 没有拿到想要的title 而是[object object]


3.2 遇到了[object object]的问题 , 没拿到想要的title值

原因 : column的title不是单纯的汉字 , 还被其他的img和span包裹着 ,  导致没提取到正确的title

解决 : 根据typeof进行判断 , 是字符串直接返回 ; 或者.props && .props.children是字符串直接返回 ; 再或者就返回空
 

      // 直接从columns配置中提取标题文本,忽略任何额外的JSX元素function getTitleText (column) {if (typeof column.title === 'string') {return column.title} else if (column.title.props &&typeof column.title.props.children === 'string') {return column.title.props.children}return '' // 如果无法直接提取文本,则返回空字符串}// 提炼状态码转换逻辑为独立函数function getStatusText (status) {switch (status) {case 1:return '维修中'case 2:return '待派单'case 3:return '待确认'case 4:return '关单'default:return status.toString() // 或者其他默认处理}}// 遍历columns0,为data中的每个对象创建一个仅含转换后数据的新对象let data1 = data.map(item => {const newItem = {}columns0.forEach(column => {const title = getTitleText(column)const dataIndex = column.dataIndexif (title && item.hasOwnProperty(dataIndex)) {// 对于'status'列,直接应用状态码转换逻辑newItem[title] =column.dataIndex === 'status'? getStatusText(item[dataIndex]): item[dataIndex]}})return newItem})console.log('data1', data1)

3.3 导出实现
 

import * as XLSX from 'xlsx'
import { saveAs } from 'file-saver'const [format, setFormat] = useState('')const handleDerive = columnsToExport => {let dataSource = []if (columnsToExport.includes(1)) {dataSource = data1} else {dataSource = data1.map(row => {const newRow = {}columnsToExport.forEach(column => {newRow[column] = row[column]})return newRow})}const worksheet = XLSX.utils.json_to_sheet(dataSource)const workbook = XLSX.utils.book_new()XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')let fileExtension = ''let mimeType = ''console.log('format', format)if (format === 'xlsx') {setDeriveMoadal(true)setFormat('xlsx')// 导出为 Excel 文件fileExtension = 'xlsx'mimeType ='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'} else if (format === 'csv') {// 导出为 CSV 文件const csv = XLSX.utils.sheet_to_csv(worksheet)const csvData = new Blob([csv], { type: 'text/csv;charset=utf-8;' })saveAs(csvData, 'export.csv')return} else if (format === 'txt') {// 导出为 TXT 文件const txt = XLSX.utils.sheet_to_txt(worksheet)const txtData = new Blob([txt], { type: 'text/plain;charset=utf-8;' })saveAs(txtData, 'export.txt')return}const excelBuffer = XLSX.write(workbook, {bookType: format,type: 'array'})const excelBlob = new Blob([excelBuffer], { type: mimeType })const url = window.URL.createObjectURL(excelBlob)const link = document.createElement('a')link.href = urllink.download = `export.${fileExtension}`document.body.appendChild(link)link.click()document.body.removeChild(link)window.URL.revokeObjectURL(url)}}useEffect(() => {if (format) {handleDerive()}}, [format])


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/671361.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

淡茶和浓茶的标准

按照《品深淡茶冲泡标准》&#xff0c;淡茶茶汤中的咖啡碱不得高于31.67mg/100mL&#xff0c;可可碱不得高于2.67mg/mL&#xff0c;茶碱不得高于1.50mg/100mL&#xff0c;茶多酚不得高于143mg/mL&#xff0c;按照各类茶叶中各物质的含量情况&#xff0c;茶水比例不得高于1:150&…

Linux网络-部署YUM仓库及NFS共享服务

目录 一.YUM仓库服务 1.YUM概述 1.1.YUM&#xff08;Yellow dog Updater Modified&#xff09; 2.准备安装源 2.1.软件仓库的提供方式 2.2.RPM软件包的来源 2.3.构建CentOS 7 软件仓库 2.4.在软件仓库中加入非官方RPM包组 3.一键安装软件包的工具&#xff1a; 好处&a…

fs-extra替代 Node内置 fs 模块,更安全、更强大的文件操作库

fs-extra 是作为替代 Node.js 内置 fs 模块创建的&#xff0c;当你的项目中引入 fs-extra 后&#xff0c;就可以像下面这样做。将所有使用 require(fs) 的地方&#xff1a; const fs require(fs) // this is no longer necessary 改成 require(fs-extra)&#xff1a; con…

im即时通讯源码/仿微信app源码+php即时通讯源码带红包+客服+禁言等系统php+uniapp开发

即时通讯(IM)系统是现代互联网应用中不可或缺的一部分&#xff0c;它允许用户进行实时的文本、语音、视频交流。随着技术的发展&#xff0c;IM系统的功能越来越丰富&#xff0c;如红包、客服、禁言等。本文将探讨如何使用PHP语言开发一个功能完备的即时通讯系统&#xff0c;包括…

Java Set集合

1. Set接口 1.1 Set接口概述 Set接口继承自Collection接口&#xff0c;所以与Collection接口中的方法基本一致&#xff0c;并没有对Collection接口进行功能上的扩充&#xff0c;只是比Collection接口更加严格。 Set集合的特点是无序且不可重复&#xff1a; 无序&#xff1a;不…

网卡自动切换AP和AC模式

AC模式搜索不到WiFi AC模式是指client模式&#xff0c;也就是可以自动接入wifi的模式 参考将外置网卡设置为 AP模式之后&#xff0c;发现搜索不到wifi了 &#xff08;换了一台ubuntu测试发现可以&#xff0c;所以不是硬件问题&#xff09; 经过nmcli device status查看设备发…

OCC笔记:图形可视化的实现方式

注&#xff1a;文中参看的occ的源码版本为7.4.0 1、实现思路概览 整体架构 主要有3大块&#xff1a;AIS&#xff08;Application Interactive Services &#xff0c;直译为&#xff1a;应用程序交互服务&#xff09;、Graphics&#xff08;图形&#xff09;、Geometry & T…

2024.05.06作业

自由发挥应用场景&#xff0c;实现登录界面。 要求&#xff1a;尽量每行代码都有注释。 #include "yuanshen.h"yuanshen::yuanshen(QWidget *parent): QWidget(parent) {//窗口相关设置this->resize(1600,910);this->setFixedSize(1600,910);//窗口标题this-…

【C语言】数据类型

有哪些数据类型&#xff1f; char - 字符数据类型&#xff0c;存储一个字符&#xff0c;大小是1字节。short - 短整型&#xff0c;存储一个整数&#xff0c;大小是2字节。int - 整型&#xff0c;存储一个整数&#xff0c;大小是4字节。long - 长整型&#xff0c;存储一个整数&…

华为 二层交换机与防火墙连通上网实验

防火墙是一种网络安全设备&#xff0c;用于监控和控制网络流量。它可以帮助防止未经授权的访问&#xff0c;保护网络免受攻击和恶意软件感染。防火墙可以根据预定义的规则过滤流量&#xff0c;例如允许或阻止特定IP地址或端口的流量。它也可以检测和阻止恶意软件、病毒和其他威…

AIGC时代重塑数字安全风控体系

大家好&#xff0c;我是herosunly。985院校硕士毕业&#xff0c;现担任算法研究员一职&#xff0c;热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名&#xff0c;CCF比赛第二名&#xff0c;科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的…

SpringSecurity6 学习

学习介绍 网上关于SpringSecurity的教程大部分都停留在6以前的版本 但是&#xff0c;SpringSecurity6.x版本后的内容进行大量的整改&#xff0c;网上的教程已经不能够满足 最新的版本使用。这里我查看了很多教程 发现一个宝藏课程&#xff0c;并且博主也出了一个关于SpringSec…