React 項目中封裝 Excel 導入導出組件:技術分享與實踐

文章目錄

  • 前言
    • 一、為什么需要封裝 Excel 組件?
    • 二、技術選型
    • 三、核心實現
      • 1. 安裝依賴
      • 2. 封裝Excel導出
      • 3. 封裝導入組件 (UploadExcel)
  • 總結


前言

在 React 項目中,處理 Excel 文件的導入和導出是常見的業務需求。無論是導出報表數據供用戶下載,還是讓用戶上傳 Excel 文件進行數據解析,一個高效、易用的組件都能極大提升開發效率和用戶體驗。本文將分享如何在 React 項目中封裝一個通用的 Excel 導入導出組件,涵蓋核心實現思路、代碼示例以及最佳實踐。


一、為什么需要封裝 Excel 組件?

  1. 統一處理邏輯:避免在多個頁面重復編寫 Excel 解析或生成代碼。
  2. 提升用戶體驗:通過統一的 UI 和交互,降低用戶學習成本。
  3. 減少錯誤:集中處理文件格式校驗、數據轉換等易錯環節。
  4. 可擴展性:支持自定義配置(如列映射、樣式調整等)。

二、技術選型

  • 導出 Excel:使用 xlsx 庫 & file-saver
  • 導入 Excel:使用 xlsx 庫解析文件內容。
  • UI 框架:基于 Ant Design 的 Upload 組件或自定義按鈕。

三、核心實現

1. 安裝依賴

	npm install xlsx file-saver @ant-design/icons# 或使用 yarnyarn add xlsx file-saver @ant-design/icons

2. 封裝Excel導出

根據泛型傳入不同的data數據類型和動態傳遞header表頭

import * as XLSX from "xlsx";
import { saveAs } from "file-saver";/***  導出Excel* @param data* @param header*/
export function exportExcel<T>(data: T[], header: string[]) {const worksheet = XLSX.utils.json_to_sheet(data, { header });// 創建工作簿const workbook = XLSX.utils.book_new();// 將工作表添加到工作簿XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");// 將工作簿轉換為二進制數據const excelBuffer = XLSX.write(workbook, { bookType: "xlsx", type: "array" });// 創建 Blob 對象const blob = new Blob([excelBuffer], { type: "application/octet-stream" });// 使用 file-saver 庫保存文件saveAs(blob, "exported_data.xlsx");
}

使用示例

import {useState} from 'react'
import { exportExcel } from "@/utils/exprotExcel";
// 這個是antd的table組件的表格多選框 selectedRowKeys, setSelectedRowKeys要綁定的狀態值
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]); 
const [selectRows, setSelectRows] = useState<IBill[]>([]); 
const header = ["accountNo","status","roomNo","carNo","tel","costName1","costName2","costName3","startDate","endDate","preferential","money","pay",
];// 多選const onSelectChange = (selectedRowKeys: React.Key[],selectedRows: IBill[]) => {setSelectedRowKeys(selectedRowKeys);setSelectRows(selectedRows);};// 多選框配置項const rowSelection = {selectedRowKeys,onChange: onSelectChange,preserveSelectedRowKeys: true,};// 這下面是結構
<Tableloading={loading}dataSource={billList}columns={columns}pagination={false}rowKey={(record) => record.accountNo}scroll={{ x: 1200 }}rowSelection={rowSelection}/><Button// 使用封裝好的Excel導出組件type="primary"onClick={() => exportExcel(selectRows, header)}icon={<DownloadOutlined />}disabled={disabled}>導出為Excel
</Button>

在這里插入圖片描述
在這里插入圖片描述


3. 封裝導入組件 (UploadExcel)

import { Upload, message } from "antd";
import type { UploadProps } from "antd";
import { InboxOutlined } from "@ant-design/icons";
const { Dragger } = Upload;import * as XLSX from "xlsx";interface ExcelRowItem {[key: number]: string; // 索引簽名,允許任意數字鍵
}interface IParms<U> {setStaffList: (staffList: (prev: U[]) => U[]) => void;headers: (keyof U)[];
}
// 處理導入的Excel數據
function handleImpotedJson<T>(jsonArr: ExcelRowItem[],headers: (keyof T)[] // 將 headers 明確為 T 的鍵數組
) {// 去掉表頭jsonArr.splice(0, 1);const jsonArrData: T[] = jsonArr.map((item: ExcelRowItem) => {console.log(item, "item");// 這樣做可以避免不用初始化對象,不用硬編碼Partialconst jsonObj: Partial<T> = {};// const jsonObj: T = {//   key: Math.floor(Math.random() * 10000000),//   name: item[0],//   region: item[1],//   role: item[2],//   phone: item[3],// };// 動態生成表頭headers.forEach((header, index) => {const value = item[index];if (value !== undefined) {jsonObj[header] = value as T[keyof T];}});return jsonObj as T;});console.log(jsonArrData, "jsonArrData");return jsonArrData;
}/***  Excel上傳組件* @param param0  傳參需要:1.useState表格數據列表 2.表頭信息 3.傳表頭的泛型* @returns*/
function UploadExcel<U>({ setStaffList, headers }: IParms<U>) {const props: UploadProps = {name: "file",multiple: true,accept: ".xls,.xlsx", // 只允許上傳 Excel 文件action: "https://www.demo.com/import",onChange(info) {console.log("我同時觸發了onChange和onDrop");const { status } = info.file;if (status !== "uploading") {const file = info.file.originFileObj; //if (file) {const reader = new FileReader();reader.onload = (e) => {const target = e.target?.result as ArrayBuffer;if (target) {const data = target; // 安全訪問const workbook = XLSX.read(data, { type: "binary" });const first_worksheet = workbook.Sheets[workbook.SheetNames[0]];const jsonArr = XLSX.utils.sheet_to_json(first_worksheet, {header: 1,});const res = handleImpotedJson<U>(jsonArr as ExcelRowItem[],headers);console.log(res, "我是最后的結果");setStaffList((prevStaffList) => {return [...prevStaffList, ...res];});// 添加這一行,開始讀取文件reader.readAsArrayBuffer(file);}}if (status === "done") {message.success(`${info.file.name} 文件已成功上傳.`);} else if (status === "error") {message.error(`${info.file.name} 文件上傳失敗.`);}},onDrop(e) {console.log("我開始拖拽了", e.dataTransfer.files);},};return (//  這個是antd的上傳組件<><Dragger {...props}><p className="ant-upload-drag-icon"><InboxOutlined /></p><p className="ant-upload-text">點擊或拖拽上傳文件哦!!!</p><p className="ant-upload-hint">支持單個文件或批量上傳。嚴禁上傳公司數據或其他受禁文件。</p></Dragger></>);
}export default UploadExcel;

使用示例:
也是引入組件,傳表頭,和你的修改狀態的setState

import UploadExcel from "@/components/UploadExcel";
import {useState} from 'react'const [staffList, setStaffList] = useState<IStaff[]>([]);const header: StaffKeys[] = ["name", "region", "role", "phone"];<UploadExcel<StaffMemberData>headers={header}setStaffList={setStaffList}/>

在這里插入圖片描述

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

總結

通過封裝 Excel 導入導出組件,我們可以將重復的邏輯抽象為可復用的模塊,提升開發效率和代碼質量。關鍵點包括:

  • 使用 xlsx 庫處理核心邏輯。
  • 結合 Ant Design 等 UI 框架提升交互體驗。
  • 通過配置化(如列映射、泛型約束)滿足不同場景需求。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/83195.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/83195.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/83195.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

RustDesk 搭建自建服務器并設置服務自啟動

目錄 0. 介紹 1. 事前準備 1.1 有公網 ip 的云服務器一臺 1.2 服務端部署包 1.3 客戶端安裝包 2. 部署 2.1 服務器環境準備 2.2 上傳服務端部署包 2.3 運行 pm2 3. 客戶端使用 3.1 安裝 3.2 配置 3.2.1 解鎖網絡設置 3.2.2 ID / 中級服務器 3.3 啟動效果 > …

基于Qt封裝數據庫基本增刪改查操作,支持多線程,并實現SQLite數據庫單例訪問

抽出來的&#xff0c;直接用就行 頭文件CPP文件使用示例 頭文件 #ifndef DATABASECOMMON_H #define DATABASECOMMON_H/** 單例封裝SQLite通用操作&#xff0c;支持多線程調用&#xff1b;可擴展兼容其他數據庫&#xff0c;照著SysRunDatabase寫&#xff0c;并且重載openDataba…

AI筆記 - 網絡模型 - mobileNet

網絡模型 mobileNet mobileNet V1網絡結構深度可分離卷積空間可分![在這里插入圖片描述](https://i-blog.csdnimg.cn/direct/aff06377feac40b787cfc882be7c6e5d.png) 參考 mobileNet V1 網絡結構 MobileNetV1可以理解為VGG中的標準卷積層換成深度可分離卷積 可分離卷積主要有…

第十五篇:MySQL 高級實戰項目:構建高可用、可觀測、性能優化一體化數據庫平臺

本篇聚焦于如何基于 MySQL 構建一個真正面向生產環境的數據庫平臺&#xff0c;集成高可用、可觀測與性能調優三大核心能力&#xff0c;助力穩定、可擴展的系統運行。 一、項目背景與目標 在實際生產環境中&#xff0c;數據庫系統需要應對以下挑戰&#xff1a; 業務高速增長帶來…

華為OD機試真題——文件目錄大小(2025 A卷:100分)Java/python/JavaScript/C++/C語言/GO六種語言最佳實現

2025 A卷 100分 題型 本文涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、測試用例以及綜合分析; 并提供Java、python、JavaScript、C++、C語言、GO六種語言的最佳實現方式! 2025華為OD真題目錄+全流程解析/備考攻略/經驗分享 華為OD機試真題《文件目錄大小》: 目錄 題…

qwen 2.5 并行計算機制:依靠 PyTorch 和 Transformers 庫的分布式能力

qwen 2.5 并行計算機制:依靠 PyTorch 和 Transformers 庫的分布式能力 完整可運行代碼: import torch import torch.nn.functional as F from transformers

TIDB創建索引失敗 mkdir /tmp/tidb/tmp_ddl-4000/1370: no such file or directory.

TIDB創建索引失敗&#xff1a;解決“mkdir /tmp/tidb/tmp_ddl-4000/1370: no such file or directory”問題 在使用 TIDB 數據庫時&#xff0c;我們有時會遇到創建索引失敗的問題。常見的錯誤信息為&#xff1a; mkdir /tmp/tidb/tmp_ddl-4000/1370: no such file or directo…

華為OD機試真題—— 最少數量線段覆蓋/多線段數據壓縮(2025A卷:100分)Java/python/JavaScript/C++/C語言/GO六種最佳實現

2025 A卷 100分 題型 本文涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、測試用例以及綜合分析; 并提供Java、python、JavaScript、C++、C語言、GO六種語言的最佳實現方式! 2025華為OD真題目錄+全流程解析/備考攻略/經驗分享 華為OD機試真題《最少數量線段覆蓋/多線段數…

EasyRTC嵌入式音視頻實時通話SDK助力AI與IoT智能硬件打造音視頻交互多場景應用

一、引言? 在數字化浪潮下&#xff0c;AI與IoT深度融合重塑智能硬件產業。實時音視頻通信是智能硬件交互的核心&#xff0c;其性能關乎用戶體驗與場景拓展。EasyRTC嵌入式音視頻實時通話SDK基于WebRTC技術&#xff0c;以輕量、易擴展的特性&#xff0c;為AI與IoT智能硬件融合…

第十四章 MQTT訂閱

系列文章目錄 系列文章目錄 第一章 總體概述 第二章 在實體機上安裝ubuntu 第三章 Windows遠程連接ubuntu 第四章 使用Docker安裝和運行EMQX 第五章 Docker卸載EMQX 第六章 EMQX客戶端MQTTX Desktop的安裝與使用 第七章 EMQX客戶端MQTTX CLI的安裝與使用 第八章 Wireshark工具…

【第4章 圖像與視頻】4.4 離屏 canvas

文章目錄 前言為什么要使用 offscreenCanvas為什么要使用 OffscreenCanvas如何使用 OffscreenCanvas第一種使用方式第二種使用方式 計算時長超過多長時間適合用Web Worker 前言 在 Canvas 開發中&#xff0c;我們經常需要處理復雜的圖形和動畫&#xff0c;這些操作可能會影響頁…

Go語言事件總線EventBus本地事件總線系統的完整實現框架

在Go語言中&#xff0c;EventBus是一種非常有用的工具&#xff0c;它通過事件驅動的編程方式&#xff0c;幫助開發者實現組件之間的解耦&#xff0c;提高代碼的可維護性和擴展性。 背景 軟件架構的發展需求&#xff1a;隨著軟件系統的規模和復雜度不斷增大&#xff0c;傳統的緊…

Go語言接口:靈活多態的核心機制

引言 Go語言的接口系統是其??面向對象編程??的核心&#xff0c;它摒棄了傳統語言的類繼承體系&#xff0c;采用獨特的??隱式實現??和??鴨子類型??設計。這種設計使得Go接口既靈活又強大&#xff0c;成為構建松耦合系統的關鍵工具。本文將深入剖析Go接口的實現機制…

DeviceNET轉EtherCAT網關:醫院藥房自動化的智能升級神經中樞

在現代醫院藥房自動化系統中&#xff0c;高效、精準、可靠的設備通信是保障患者用藥安全與效率的核心。當面臨既有支持DeviceNET協議的傳感器、執行器&#xff08;如藥盒狀態傳感器、機械臂限位開關&#xff09;需接入先進EtherCAT高速實時網絡時&#xff0c;JH-DVN-ECT疆鴻智能…

android實現使用RecyclerView詳細

顯示頁面代碼&#xff1a;activity_category_inventory.xml代碼&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android" xmlns:app"http://schemas.and…

【SpringBoot實戰】優雅關閉服務

文章目錄 一、什么是優雅關閉&#xff1f;二、優雅關閉的核心步驟三、SpringBoot優雅關閉實現四、關鍵注意事項1. 超時時間必須配置2. 信號支持局限性3. 特殊請求處理 五、底層實現原理六、總結 一、什么是優雅關閉&#xff1f; 優雅關閉&#xff08;Graceful Shutdown&#x…

C++哈希表:unordered系列容器詳解

本節目標 1.unordered系列關聯式容器 2.底層結構 3.模擬實現 4.哈希的應用 5.海量數據處理面試題 unordered系列關聯式容器 在c98中&#xff0c;STL提供了底層為紅黑樹結構的一系列關聯式容器&#xff0c;在查詢時效率可以達到logN&#xff0c;即最差的情況下需要比較紅…

java操作服務器文件(把解析過的文件遷移到歷史文件夾地下)

第一步導出依賴 <dependency><groupId>org.apache.sshd</groupId><artifactId>sshd-core</artifactId><version>2.13.0</version></dependency> 第二步寫代碼 public void moveFile( List<HmAnalysisFiles> hmAnalys…

Oracle OCP認證的技術定位怎么樣?

一、引言&#xff1a;Oracle OCP認證的技術定位? Oracle Certified Professional&#xff08;OCP&#xff09;認證是數據庫領域含金量最高的國際認證之一&#xff0c;其核心價值在于培養具備企業級數據庫全生命周期管理能力的專業人才。隨著數字化轉型加速&#xff0c;OCP認證…

TK海外搶單源碼/指定卡單

? 搶單源碼&#xff0c;有指定派單&#xff0c;打針&#xff0c;這套二改過充值跳轉客服 前端vue 后端php 兩端分離 可二開 可以指定卡第幾單&#xff0c;金額多少&#xff0c; 前后端開源 PHP7.2 MySQL5.6 前端要www.域名&#xff0c;后端要admin.域名 前端直接靜態 偽靜…