手把手教你用React做一个Excel导入功能,看完就能用!

前言

最近项目需要做个Excel导入功能,网上找了一圈发现要么太复杂要么不能用,干脆自己写一个。这篇文章就是记录整个开发过程,代码可以直接复制粘贴到你的项目里用。

先看看效果

这个组件能干啥:

  • 上传Excel文件(.xlsx和.xls都支持)
  • 自动识别表格内容,第一行当表头
  • 支持多个工作表切换
  • 数据预览,还能编辑
  • 一键导入到系统

开始写代码

第一步:安装依赖

复制代码
npm install xlsx antd

第二步:创建组件

ini 复制代码
import { Button, Select, Table, Upload, Modal } from "antd";
import { useState } from "react";
import * as XLSX from "xlsx";

const TableDataImport = () => {
  // 这些状态用来存数据
  const [tableData, setTableData] = useState([]); // 表格数据
  const [columns, setColumns] = useState([]); // 表格列
  const [tableLoading, setTableLoading] = useState(false); // 加载状态
  const [tableFile, setTableFile] = useState(); // 上传的文件
  const [sheetNames, setSheetNames] = useState([]); // 工作表列表
  const [isModalOpen, setIsModalOpen] = useState(false); // 弹窗显示

  // 核心方法:处理文件上传
  const handleUpload = (file, sheetName) => {
    // 清空之前的数据
    setColumns([]);
    setTableData([]);
    setTableLoading(true);

    // 用FileReader读文件
    const reader = new FileReader();
    reader.onload = (e) => {
      // 把文件转成数组
      const data = new Uint8Array(e.target.result);
      
      // 用xlsx库读Excel
      const workbook = XLSX.read(data, { type: "array" });
      
      // 获取工作表(如果指定了就用指定的,否则用第一个)
      const worksheet = sheetName
        ? workbook.Sheets[sheetName]
        : workbook.Sheets[workbook.SheetNames[0]];

      // 转成JSON数据
      const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });

      // 处理数据:第一行当表头,后面的当数据
      if (jsonData.length > 0) {
        const newData = [];
        jsonData.slice(1).forEach((item, itemIndex) => {
          if (item.length === 0) return;
          
          const obj = { key: itemIndex };
          // 把表头和数据对应起来
          jsonData[0].forEach((header, index) => {
            obj[header] = item[index];
          });
          newData.push(obj);
        });

        // 生成表格列配置
        const columns = jsonData[0].map(header => ({
          title: header,
          dataIndex: header,
          key: header,
          align: "center",
        }));

        setColumns(columns);
        setTableData(newData);
      }

      setTableLoading(false);
    };
    reader.readAsArrayBuffer(file);
  };

  // 切换工作表
  const handleChange = (value) => {
    if (tableFile) handleUpload(tableFile, value);
  };

  // 确定导入
  const handleOk = () => {
    // 这里调用你的导入接口
    console.log('要导入的数据:', tableData);
    setIsModalOpen(false);
    // 清空数据
    setTableData([]);
    setColumns([]);
  };

  return (
    <div>
      {/* 弹窗 */}
      <Modal
        title="Excel导入"
        open={isModalOpen}
        onOk={handleOk}
        onCancel={() => setIsModalOpen(false)}
        width={800}
        okText="导入"
        cancelText="取消"
      >
        <div style={{ margin: "20px 0" }}>
          {/* 文件上传 */}
          <Upload
            beforeUpload={(file) => {
              // 检查文件类型
              const isExcel = /.(xlsx|xls)$/.test(file.name.toLowerCase());
              if (!isExcel) {
                alert("请上传Excel文件(.xlsx 或 .xls)");
                return false;
              }
              
              setTableFile(file);
              handleUpload(file);
              return false; // 阻止自动上传
            }}
          >
            <Button>上传Excel文件</Button>
          </Upload>

          {/* 工作表选择 */}
          {sheetNames.length > 0 && (
            <div style={{ marginTop: 20 }}>
              <span>选择工作表:</span>
              <Select
                style={{ width: 200, marginLeft: 10 }}
                onChange={handleChange}
                options={sheetNames.map(name => ({
                  label: name,
                  value: name
                }))}
              />
            </div>
          )}
        </div>

        {/* 数据预览表格 */}
        <Table
          loading={tableLoading}
          dataSource={tableData}
          columns={columns}
          scroll={{ y: 400 }}
          size="small"
        />
      </Modal>

      {/* 触发按钮 */}
      <Button onClick={() => setIsModalOpen(true)} type="primary">
        导入Excel
      </Button>
    </div>
  );
};

export default TableDataImport;

关键点解释

1. 文件读取流程

javascript 复制代码
用户上传文件 → FileReader读取 → xlsx库解析 → 转成JSON → 显示在表格里

2. 数据转换逻辑

Excel的第一行自动变成表格的表头,下面的行变成数据行。比如:

css 复制代码
Excel内容:
姓名    年龄    城市
张三    25     北京
李四    30     上海

转换后:
columns: [{title: '姓名', dataIndex: '姓名'}, {title: '年龄', dataIndex: '年龄'}, {title: '城市', dataIndex: '城市'}]
data: [{姓名: '张三', 年龄: 25, 城市: '北京'}, {姓名: '李四', 年龄: 30, 城市: '上海'}]

3. 工作表切换

如果你的Excel有多个工作表,组件会自动识别并让你选择用哪个。

怎么用

1. 复制代码到你的项目

把上面的代码复制到一个新文件,比如 ExcelImport.tsx

2. 在需要的地方引入

javascript 复制代码
import ExcelImport from './ExcelImport';

// 在你的页面里
<ExcelImport />

3. 修改导入逻辑

在 handleOk 方法里,把 console.log 改成你的实际导入逻辑:

scss 复制代码
const handleOk = () => {
  // 调用你的API
  api.importData(tableData).then(() => {
    message.success('导入成功!');
    setIsModalOpen(false);
  });
};

常见问题

Q: 为什么上传文件后没反应?

A: 检查浏览器控制台有没有报错,通常是文件格式不对或者xlsx库没装好。

Q: 数据格式不对怎么办?

A: 确保Excel第一行是表头,数据从第二行开始。空行会被自动过滤掉。

Q: 想支持更多文件格式?

A: 在 beforeUpload 里加文件类型判断就行。

总结

这个组件其实不难,核心就是:

  1. 用FileReader读文件
  1. 用xlsx库解析Excel
  1. 把数据转成表格能用的格式

本期内容就到这里,各位大佬觉得有用可以收藏+关注,另外主页有火柴能点着的干货哦!!

相关推荐
一袋米扛几楼9810 分钟前
【Git】规范化协作:详解 GitHub 工作流中的 Issue、Branch 与 Pull Request 最佳实践
前端·git·github·issue
网络点点滴23 分钟前
前端与后端的区别与联系
前端
EnCi Zheng1 小时前
M5-markconv自定义CSS样式指南 [特殊字符]
前端·css·python
kyriewen1 小时前
你的网页慢,用户不说直接走——前端性能监控教你“读心术”
前端·性能优化·监控
广州华水科技1 小时前
北斗GNSS变形监测在大坝安全监测中的应用与优势分析
前端
前端老石人1 小时前
前端开发中的 URL 完全指南
开发语言·前端·javascript·css·html
CAE虚拟与现实1 小时前
五一假期闲来无事,来个前段、后端的说明吧
前端·后端·vtk·three.js·前后端
Sarvartha1 小时前
三目运算符
linux·服务器·前端
晓晨的博客1 小时前
ROS1录制的bag包转换为ROS2格式
前端·chrome
Wect1 小时前
LeetCode 72. 编辑距离:动态规划经典题解
前端·算法·typescript