携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
日常需求中,可能存在业务场景需要前端做以下处理
- 校验导入的Excel文件是否有数据
- 对Excel文件转化为Json格式
- Json转化为Excel文件
xlsx插件提供了以上问题的解决方案,以下以小demo为例简单说明实现:
一、使用npm安装xlsx
npm i xlsx
二、前端获取Excel文件数据
1、封装从 excel 文件读取数据
传参需要
- excelRcFileBuffer: excel 文件
- index: excel 文件中的第几张表
- moduleName: 表格中表头映射对应的key值的模板name
通过函数parseAndServeChange见步骤3进行数据格式转换
转换前
转换后
import * as xlsx from 'xlsx';
import type { WorkBook } from 'xlsx';
/**
* 从 excel 文件读取数据
* @param excelRcFileBuffer excel 文件
* @param index 第几张表
* @param moduleName 映射模板name
*/
export function importExcelFromBuffer<Item = any>(excelRcFileBuffer: ArrayBuffer, index:number = 0, moduleName: string): Item[] {
if (moduleName === '') {
console.log('请输入对应的映射模板name');
return []
}
// 读取表格对象
const workbook = xlsx.read(excelRcFileBuffer, {type: 'buffer'});
// 找到对应index表
const sheetNames = workbook.SheetNames;
const sheet = workbook.Sheets[sheetNames[index]];
let outdata: Item[] = xlsx.utils.sheet_to_json(sheet);
outdata = parseAndServeChange(outdata, fieldMapping[moduleName]);
console.log('data========================', outdata);
if (outdata.length === 0) {
console.log('请检查模板是否正确/内容是否为空');
}
// 读取内容
return outdata;
}
2、封装映射模板fieldMapping
表格中表头对应后端映射的key值
const UserInfo = {
name: "姓名",
phone: "联系电话",
age: "年龄",
local: "籍贯"
}
export {
UserInfo,
}
3、处理读取出来数据转换为服务器可读取的数据/将服务器数据转换为Excel表头对应字段数据
即[{姓名: "张三",联系电话:13800013800,年龄: "28",籍贯:"广东广州"}]和[{name:"张三", phone: 13800013800, 年龄: 18, local: "广东广州"}]数据根据对应类型相互转换
把读取出来得数据变为组后可以传递给服务器的数据,传参需要:
- data: excel解析数据
- revertChart: 字段映射
返回值:
- returns: 返回对应格式数据
import * as fieldMapping from './fieldMapping';
/**
* @description 把数据进行不同类型转换
* @param data excel解析数据
* @param revertChart 字段映射
* @param type 字段映射 type为out则为数据变为组后可以传递给服务器的数据, 否则服务器的数据转换为Excel表头对应字段数据
* @returns 返回对应格式数据
*/
const parseAndServeChange = (data: any, revertChart: any, type: string = 'out') => {
const arr: any = [];
data.forEach((item: any) => {
const obj = {};
Object.keys(revertChart).forEach(key => {
let _key = type === 'out' ? key : revertChart[key]
let _val = type === 'out' ? item[revertChart[key]] : item[key]
obj[_key] = _val;
})
arr.push(obj);
});
return arr;
};
4、在组件中使用
import { importExcelFromBuffer } from '@/utils/xlsx/utils'
const excelMimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
import { Button, Upload } from 'antd';
...
const Index: React.FC = () => {
const [excelData, setExcelData] = useState<any[]>([]);
// 获取文件并解析
const localExcelToData = async (options: any) => {
const {file, onError, onSuccess} = options;
try {
// xlsx 导入 excel
const excelData = importExcelFromBuffer<any>(await (file).arrayBuffer(), 0, 'UserInfo');
// 设置 data
setExcelData(excelData);
if (onSuccess) onSuccess(excelData, new XMLHttpRequest());
} catch (e) {
if (onError) onError(e)
}
}
return (
<PageContainer>
<Upload accept={excelMimeType} customRequest={localExcelToData}>
<Button type="primary">前端Excel转Data</Button>
</Upload>
</PageContainer>
);
}
三、前端导出Excel文件
1、封装从 json 转 excel 文件
传参需要
- dataSource: JSON 数组
- moduleName: 映射模板name
- sheetName: 表名
- fileName: 文件名
import * as xlsx from 'xlsx';
import type { WorkBook } from 'xlsx';
import * as fieldMapping from './fieldMapping';
/**
* 导出 excel 文件
* @param dataSource JSON 数组
* @param moduleName 映射模板name
* @param sheetName 表名
* @param fileName 文件名
*/
export function exportExcelFile(dataSource: any[], moduleName: string, sheetName = '表1', fileName = 'example.xlsx') {
const inputData = parseAndServeChange(dataSource, fieldMapping[moduleName], 'input')
const jsonWorkSheet = xlsx.utils.json_to_sheet(inputData);
const workBook: WorkBook = {
SheetNames: [sheetName],
Sheets: {
[sheetName]: jsonWorkSheet,
}
};
return xlsx.writeFile(workBook, fileName);
}
2、在组件中使用
import { exportExcelFile } from '@/utils/xlsx/utils'
import { Button } from 'antd';
...
const Index: React.FC = () => {
const [excelData, setExcelData] = useState<any[]>([]);
return (
<PageContainer>
<Button
disabled={excelData.length === 0}
onClick={() => exportExcelFile(excelData, 'UserInfo')}
type="primary"
>
前端Data转Excel
</Button>
</PageContainer>
);
}