XLSX插件使用 — 导入导出(含中文表头)(React+Antd 对上传表格做数据格式验证)

本文介绍了在React项目中,使用js-xlsx库实现前端导出Excel,并对上传的表格数据进行格式验证。详细讲解了如何处理包含中文表头的数据,以及简单导入和数据验证的实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需求说明

1.需要前端做数据导出(非调用接口)
2.需要对上传的表格数据做验证,不通过验证需要提示格式不正确,阻拦上传

技术栈介绍

React+Antdesign+XLSX

js-xlsx 介绍

SheetJS出品的js-xlsx是一款非常方便的只需要纯JS即可读取和导出excel的工具库,功能强大,支持格式众多,支持xls、xlsx、ods(一种OpenOffice专有表格文件格式)等十几种格式。

GitHub地址:https://github.com/SheetJS/sheetjs

官网地址:https://sheetjs.com/

React使用文档:https://docs.sheetjs.com/docs/demos/frontend/react

导出的简单使用

首先插件的几个重要的名词对应如下图

在这里插入图片描述

根据数据类型,写法可分为

  1. 纯数组

    /**
     * 导出 excel 文件
     * @param array JSON 数组
     * @param sheetName 第一张表名
     * @param fileName 文件名
     */
    export function exportExcelFile(array: any[], sheetName = '表1', fileName = 'example.xlsx') {
      const jsonWorkSheet = xlsx.utils.json_to_sheet(array);
      const workBook: WorkBook = {
        SheetNames: [sheetName],
        Sheets: {
          [sheetName]: jsonWorkSheet,
        }
      };
      return xlsx.writeFile(workBook, fileName);
    }
    
  2. 对象数组(后端返回的数组是一堆对象)(第一行为中文表头

      export function exportExcelFile(array: any[], sheetName = '表1', fileName = 'example.xlsx') {
        // 属性名数组
        const header = ['name', 'age', 'addr'];
        // 最终数组 第一行为中文表头
        let finalData = [
          {
            name: '账号',
            age: '密码',
            addr: '地址',
          },
        ]; 
        array?.forEach((item) => {
          const pickedItem = item?.map((e) => pick(e, header)); // 此方法是loadash中,找到当前对象e中,对应header属性名称的属性,返回一个对象
          if (pickedItem) {
            finalData.push(...pickedItem);
          }
        });
    
        const jsonWorkSheet = xlsx.utils.json_to_sheet(finalData,header);
        const workBook: WorkBook = {
          SheetNames: [sheetName],
          Sheets: {
            [sheetName]: jsonWorkSheet,
          }
        };
        return xlsx.writeFile(workBook, fileName);
      }
    

导入的简单使用

  1. 简单导入,获取表格数据

    /**
     * 从 excel 文件读取数据
     * @param excelRcFileBuffer excel 文件
     */
    export function importExcelFromBuffer<Item = any>(excelRcFileBuffer: ArrayBuffer): Item[] {
      // 读取表格对象
      const workbook = xlsx.read(excelRcFileBuffer, {type: 'buffer'});
      // 找到第一张表
      const sheetNames = workbook.SheetNames;
      const sheet1 = workbook.Sheets[sheetNames[0]];
      // 读取内容
      return xlsx.utils.sheet_to_json(sheet1);
    }
    
  2. 结合业务场景,需要对上传数据做校验,此demo简单校验是否为中文是否为数字

    // 此处的onChange方法为 Antd的Upload组件的API
    onChange(info) {
      // 文件状态为done时,可获取完整文件流
      if (info.file.status === 'done') {
        const fileReader = new FileReader();
        // 是否成功的标识
        let canPass = true;
        fileReader.onload = (e) => {
          const data = e.target.result;
          // 将获取的文件流 以数组形式读取
          const workBook = XLSX.read(data, { type: 'array' });
          // 获取当前文件第一个表的表名
          const workSheetNames = workBook.SheetNames[0];
          // 拿到对应的表
          const workSheet = workBook.Sheets[workSheetNames];
          // 通过需要的数据属性,把数据整理成对象数组
          const excelData = XLSX.utils.sheet_to_json(workSheet, {
            header: Object.keys(['name','age','addr']),
            raw: false,
          });
          // 删除第一行中文表头
          excelData.shift();
          // 如果上传的空数据就 不通过
          if (!(excelData && excelData.length > 0)) {
            canPass = false;
          }else{
            // name不允许有中文,age需要是数字
            const noPass= excelData.find(e=>hasChinese(e.name)||!isNumber(e.age))
            if(noPass){
              canPass = false;
            }
          }
         
          if (canPass) {
            const fileName = info.file.name;
            // 成功的回调(自定义的)
            onSuccess(excelData, fileName);
            message.success(`${fileName} 上传成功`);
          } else {
            message.warning('请按照格式填写');
          }
        };
      } else if (info.file.status === 'error') {
        message.error(`${info.file.name} 上传失败`);
      }
    }
    
    //**************单独方法
    
    // 判断是否含有汉字
    export const hasChinese = (str) => {
      const reg = /[\u4E00-\u9FA5]/g;
      return reg.test(str);
    };
    
    // 判断是否为数字
    export const isNumber = (str) => {
      const reg = /^(-?\d+)(\.\d+)?$/;
      return reg.test(str);
    };
    

有个博主讲了更多业务场景可查看:https://www.jianshu.com/p/f9ba3dd3cd4f

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值