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

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

 




选择了全部 , 不能选其他 



全部导出



部分导出



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

           <Dropdown
                menu={{
                  items: [
                    {
                      label: (
                        <a
                          onClick={() => {
                            setFormat('xlsx')
                          }}
                        >
                          导出Excel
                        </a>
                      ),
                      key: '1'
                    },

                    {
                      label: (
                        <a
                          onClick={() => {
                            setFormat('csv')
                          }}
                        >
                          导出CSV
                        </a>
                      ),
                      key: '2'
                    },
                    {
                      label: (
                        <a
                          onClick={() => {
                            setFormat('txt')
                          }}
                        >
                          导出TXT
                        </a>
                      ),
                      key: '3'
                    }
                  ]
                }}
              >
                <Button
                  type='primary'
                  ghost
                  icon={
                    <img
                      src={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>

              <Checkbox
                style={{ marginTop: 20, marginRight: 15 }}
                value={'工单编号'}
              >
                工单编号
              </Checkbox>
              <Checkbox
                style={{ marginTop: 20, marginRight: 15 }}
                value={'地点'}
              >
                地点
              </Checkbox>
              <Checkbox
                style={{ marginTop: 20, marginRight: 15 }}
                value={'位置'}
              >
                位置
              </Checkbox>
              <Checkbox
                style={{ marginTop: 20, marginRight: 15 }}
                value={'设备类型'}
              >
                设备类型
              </Checkbox>
              <Checkbox
                style={{ marginTop: 20, marginRight: 15 }}
                value={'品牌/型号'}
              >
                品牌/型号
              </Checkbox>
              <Checkbox
                style={{ marginTop: 20, marginRight: 15 }}
                value={'设备编号'}
              >
                设备编号
              </Checkbox>
              <Checkbox
                style={{ 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))
    }
  }

// 拿到实时的value2
  useEffect(() => {
    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.dataIndex

      if (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.dataIndex

          if (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 = url
      link.download = `export.${fileExtension}`
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      window.URL.revokeObjectURL(url)
    }
  }
  useEffect(() => {
    if (format) {
      handleDerive()
    }
  }, [format])


 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

零基础编程学python:如何从零开始学习并使用Python编程语言

零基础编程学python&#xff1a;如何从零开始学习并使用Python编程语言 Python是一种非常流行的编程语言&#xff0c;由于其简单的语法和强大的功能&#xff0c;使其成为初学者和专业开发者的首选。无论您是数据科学家、网络开发者还是自动化工程师&#xff0c;Python都能提供必…

Excel利用数据透视表将二维数据转换为一维数据(便于后面的可视化分析)

一维数据&#xff1a;属性值都不可合并&#xff0c;属性值一般在第一列或第一行。 二维数据&#xff1a;行属性或列属性是可以继续合并的&#xff0c;如下数据中行属性可以合并为【月份】 下面利用数据透视表将二维数据转换为一维数据&#xff1a; 1、在原来的数据上插入数据透…

(论文阅读-优化器)Selectivity Estimation using Probabilistic Models

目录 摘要 一、简介 二、单表估计 2.1 条件独立Condition Independence 2.2 贝叶斯网络Bayesian Networks 2.3 查询评估中的贝叶斯网络 三、Join选择性估计 3.1 两表Join 3.2 概率关系模型 3.3 使用PRMs的选择性估计 四、PRM构建 4.1 评分标准 4.2 参数估计 4.3 结…

Adobe Illustrator 2024 for Mac:矢量图形设计软件

Adobe Illustrator 2024 for Mac是一款专为Mac用户设计的行业标准矢量图形设计软件。该软件以其卓越的性能和丰富的功能&#xff0c;为设计师和艺术家们提供了一个全新的创意空间。 作为一款矢量图形软件&#xff0c;Adobe Illustrator 2024 for Mac支持创建高质量的矢量图形&a…

Docker 的网络实现

简介 标准的 Docker 支持以下 4 类网络模式&#xff1a; 1&#xff09;host 模式&#xff1a;使用 --nethost 指定 2&#xff09;container 模式&#xff1a;使用–netcontainer:NAME_or_ID 指定 3&#xff09;none模式&#xff1a;使用 --netnone 指定 4&#xff09;bridge 模…

BEV下统一的多传感器融合框架 - FUTR3D

BEV下统一的多传感器融合框架 - FUTR3D 引言 在自动驾驶汽车或者移动机器人上&#xff0c;通常会配备许多种传感器&#xff0c;比如&#xff1a;光学相机、激光雷达、毫米波雷达等。由于不同传感器的数据形式不同&#xff0c;如RGB图像&#xff0c;点云等&#xff0c;不同模态…

JavaScript注释规范

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃 &#xff0c;大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端基础路线”&#xff0c;可获…

基于C++基础知识的循环语句

一、while循环 while循环语句形式如下&#xff1a; while(表达式){语句 } 循环每次都是执行完语句后回到表达式处重新开始判断&#xff0c;重新计算表达式的值&#xff0c;一旦表达式的值为假就退出循环。用花括号括起来的多条简单语句&#xff0c;花括号及其包含的语句被称…

ContEA阅读笔记

Facing Changes: Continual Entity Alignment for Growing Knowledge Graphs 面对变化&#xff1a;不断增长的知识图谱的持续实体对齐 Abstract 实体对齐是知识图谱(KG)集成中一项基本且重要的技术。多年来&#xff0c;实体对齐的研究一直基于知识图谱是静态的假设&#xff…

Day 41 343.整数拆分 96.不同的二叉搜索树

整数拆分 给定一个正整数 n&#xff0c;将其拆分为至少两个正整数的和&#xff0c;并使这些整数的乘积最大化。 返回你可以获得的最大乘积。 示例 1: 输入: 2输出: 1解释: 2 1 1, 1 1 1。 示例 2: 输入: 10输出: 36解释: 10 3 3 4, 3 3 4 36。说明: 你可以假设 …

Java基础教程 - 5 数组

更好的阅读体验&#xff1a;点这里 &#xff08; www.doubibiji.com &#xff09; 更好的阅读体验&#xff1a;点这里 &#xff08; www.doubibiji.com &#xff09; 更好的阅读体验&#xff1a;点这里 &#xff08; www.doubibiji.com &#xff09; 5 数组 前面我们保存数据…

前端基础学习html(1)

1.标题标签.h1,h2...h6 2.段落标签p 换行标签br 3.加粗strong(b) /倾斜em(i) /删除 del(s) /下划线ins(u) 4.盒子&#xff1a;div //一行一个 span//一行多个 5.img :src alt title width height border 图片src引用&#xff1a;相对路径 上级/同级/中级 绝对路径&#xff…

直播话术核心逻辑,学了轻松提高销量!沈阳直播运营培训

直播话术到底该怎么说&#xff1f; 产品话术说得好&#xff0c;直播间一次就能卖出去上万件产品&#xff1b;产品话术说不好&#xff0c;直播间半个月也卖不出去10件产品。 我们上次就有跟大家说过产品话术的具体流程&#xff0c;但发现还有更多朋友居然还是不能够很好地完成一…

2024/5/6 QTday1

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

一个简单的仓库出入库管理软件的流程是什么样的?有哪些功能?

身为仓库文员&#xff0c;我深知仓库管理对于公司运营的重要性。仓库是公司物资的中转站&#xff0c;其管理的好坏直接关系到公司的运营效率和成本控制。然而&#xff0c;传统的仓库管理方式往往存在着效率低下、易出错等问题&#xff0c;为了解决这些问题&#xff0c;我们需要…

uboot图形界面配置

文章目录 一、环境安装二、配置默认项2.图形界面 三、图形配置项的来源1.mainmenu主界面 一、环境安装 &#x1f4a6;uboot 或 Linux 内核可以通过输入“make menuconfig”来打开图形化配置界面&#xff0c;menuconfig是一套图形化的配置工具&#xff0c;需要 ncurses 库支持。…

2024年电工杯数学建模竞赛A题B题思路代码分享

您的点赞收藏是我继续更新的最大动力&#xff01; 欲获取更多电工杯学习资料&#xff0c;可点击如下卡片链接 点击链接加入群聊【2024电工杯】&#xff1a;http://qm.qq.com/cgi-bin/qm/qr?_wv1027&k_PrjarulWZU8JsAOA9gnj_oHKIjFe195&authKeySbv2XM853pynlnXiv6M58…

解决github的remote rejected|git存储库的推送保护

前言 git存储库的推送保护。当你试图推送代码到GitHub仓库时&#xff0c;由于存在与主分支&#xff08;master&#xff09;相关的仓库规则违规行为&#xff0c;推送会被拒绝了。这种保护机制帮助确保只有经过授权和符合规定的代码才能被合并到主分支&#xff0c;从而保护了主分…

网络聊天室:通过Servlet和JSP,结合session和application实现(文末附源码)

目录 一.成品效果 二.代码部分 chat.jsp ChatServlet 一.成品效果 在启动成功后&#xff0c;我们就可以在任意俩个浏览器页面中相互发消息&#xff0c;如图所示左边屏幕使用的是Edge浏览器&#xff0c;右图使用的是火狐浏览器。当然笔者这里只是简单实现最基本的一些功能&…

【LeetCode刷题记录】105. 从前序与中序遍历序列构造二叉树 106. 从中序与后序遍历序列构造二叉树

105 从前序与中序遍历序列构造二叉树 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,1…