需求说明

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组件的APIonChange(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