手把手教你用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. 把数据转成表格能用的格式

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

相关推荐
艾小码6 小时前
JSON数据处理太头疼?这4个技巧让你秒变高手!
前端·javascript·json
庚云6 小时前
前端项目中 .env 文件的原理和实现
前端·面试
10share6 小时前
【vite-vue】demo项目创建
前端
Mintopia6 小时前
用 Next.js 打造全栈文件上传(S3 / Cloudinary)——从字节到云端的奇妙旅程
前端·javascript·next.js
@HNUSTer6 小时前
基于 HTML、CSS 和 JavaScript 的智能图像灰度直方图分析系统
开发语言·前端·javascript·css·html
一枚前端小能手6 小时前
🔄 异步代码执行顺序又搞混了?事件循环机制一次性给你讲透
前端·javascript
Mintopia6 小时前
小模型 vs 大模型:WebAI 轻量化部署的技术路径
前端·javascript·aigc
小猪猪屁7 小时前
HBuilderX 云打包太慢?手把手教你 Android Studio 离线 SDK 打包 APK
前端·uni-app·android studio
梨子同志7 小时前
React Router v6
react.js