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

2024-05-06 17:28

本文主要是介绍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])


 

这篇关于react + xlsx 表格导出功能 全部实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/964908

相关文章

Vue学习笔记:拦截器

原文地址 Vue可以对http request和http response添加全局拦截,最典型的例子就是在请求头里添加token,和监测是否登录,如果没有登录则跳转到登录页面。 main.js中添加拦截器的代码: 1. request 拦截器 //request 拦截器,在请求头中加tokenaxios.interceptors.request.use(config => {if (lo

css3属性之background-size兼容ie8方案

解决方案 在ie8浏览器可能背景图片无法自适应全屏,这时候加入设置filter属性即可解决问题,同时加入height:100 <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><style>.bg{background: #EAEAEA;height: 100%;background

vue cli4之Eslint初使用

一.介绍 ESLint 是在 ECMAScript/JavaScript 代码中识别和报告模式匹配的工具,它的目标是保证代码的一致性和避免错误。在许多方面,它和 JSLint、JSHint 相似,除了少数的例外: ESLint 使用 Espree 解析 JavaScript。ESLint 使用 AST 去分析代码中的模式ESLint 是完全插件化的。每一个规则都是一个插件并且你可以在运行时添加

vue router路由解析

一、前言 Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。 二、安装 1.安装包 npm install vue-router 2.项目引用 在cli4脚手架目录router下index.js中引用 import Vue from 'vue'import VueRouter from 'vue-rou

vue多语言插件vue-i18n

安装vue-i18n npm install vue-i18n -S 使用 1.在main.js中引入vue-i18n import VueI18n from 'vue-i18n'Vue.use(VueI18n) 2.vue-i18n初始化 const i18n = new VueI18n({locale: 'cn', // 默认语言messages}) 3.vue-i

Vue.js之Socket.IO 使用

一.前言 在很多需求业务中,都需要浏览器和服务器实时通信来实现功能,比如:扫码登录(扫码后,手机确认登录,PC网页完成登录并跳转)、订单语言提醒等,这些都是建立在两端实时通信的基础上的。对前端而言,来实现浏览器和服务器实时通信,最好的选择就是Socket.IO库,能够快速的实现两端实时通信功能。 1、什么是 Socket.IO? Socket.IO是一个WebSocket库,可以在浏览器和服

Vue之组件间的数据通信

一、父组件与子组件传值 1.pros 通过 Prop 父组件向子组件传递数据。props是单向绑定的,即只能父组件向子组件传递,不能反向,是 Vue 的设计理念之单向数据流。 2.$emit 官方说法是触发当前实例上的事件。附加参数都会传给监听器回调。$emit 绑定一个自定义事件event,当这个这个语句被执行到的时候,就会将参数arg传递给父组件,父组件通过@event监听并接收参数。

ES6之Promise用法解析

一.Promise是什么 promise是一个对象,对象和函数的区别就是对象可以保存状态,函数不可以(闭包除外) 并未剥夺函数return的能力,因此无需层层传递callback,进行回调获取数据 主要用于异步计算可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果可以在对象之间传递和操作promise,帮助我们处理队列代码风格,容易理解,便于维护,多个异步等待合并便于解决 二.实例

利用Socket在计算机本地实现通信(二)

欢迎访问我的博客:konosuba.xyz 本文主要是在计算机本地使用基于TCP协议的Socket建立服务端与客户端的连接与基本通信 系统:Windows 10 软件:Visual studio 2019 语言:C++ Socket通信实现步骤 创建ServerSocket和Socket 打开连接到的Socket的输入/输出流 按照协议对Socket进行读/

利用opencv与Socket实现树莓派获取摄像头视频和灰度重心发送到电脑

使用树莓派原装CSI摄像头录制视频并利用灰度重心法获取重心,将图像和重心数据通过Socket实时传输到电脑上 因为需要实现程序一启动便打开摄像头计算数据,同时启动Socket服务器等待客户端连接,所以利用C++11中的thread库通过多线程实现程序 树莓派-服务端 #include <iostream>#include <unistd.h>#include <cstring>#inc