持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
前言
在b端产品开发中经常需要使用到表格,为了方便离线查看数据,很多时候需要导出excel或者csv文件进行浏览。 本篇文章实现了xlsx文件的导入导出,以及对接antdesign的Table组件。
搭建界面
包含导入,导出按钮,以及一个antdesign的Table组件
import { useState } from 'react';
import { Table, Button, Upload } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import styled from 'styled-components';
import * as XLSX from "xlsx";
const Wrapper = styled.div`
width: 600px;
margin: 0 auto;
`
export default function Demo() {
const [dataSource, setDataSource] = useState([])
const [columns, setColumns] = useState([
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: '住址',
dataIndex: 'address',
key: 'address',
},
]);
return <Wrapper>
< div className='btns' >
<Button onClick={exportXlsx}>导出</Button>
<Upload {...UploadProps}>
<Button icon={<UploadOutlined />}>导入</Button>
</Upload>
</div >
<Table dataSource={dataSource} columns={columns} />
</Wrapper >;
}
效果图
xlsx api介绍
该package支持多种文件的读取与写入,本篇文章以xlsx与csv文件为主。
导出
-
XLSX.utils.book_new()
创建一个空的excel对象
-
XLSX.utils.aoa_to_sheet(dataSource, columns)
根据dataSource与columns创建一个sheet。(sheet就是excel文件中的一页)
-
XLSX.utils.book_append_sheet()
将创建的一个sheet放到空的excel对象中
-
XLSX.writeFile
将excel对象写入到系统磁盘中
导入
-
XLSX.read
读取本地的excel或者csv文件
-
workbook.SheetNames[n]
获取读取的文件的第n个sheet页
-
XLSX.utils.sheet_to_json
将读取的文件转换为json格式
实现导入xlsx
确定导入文件的类型
const UploadProps = {
accept: ".xlsx",
// 文件上传之前的回调
beforeUpload: importXLsx
}
读取文件
我们使用的antdesign的Upload组件,需要在上述的importXlsx中编写逻辑。
为了防止文件读取完毕后,onload回调还没注册,所以将onload写在readAsBinaryString之前。
const importXLsx = (file) => {
// 创建一个file读取器
const fileReader = new FileReader();
// 文件读取完毕后的回调,
fileReader.onload = ((e) => {
const workbook = XLSX.read(e.target.result, {
type: "binary",
});
const wsname = workbook.SheetNames[0];
const sheetJson = XLSX.utils.sheet_to_json(workbook.Sheets[wsname]);
// 将数据转换为Table组件所需格式
const ds = dataToDatasource(sheetJson);
setDataSource(ds)
})
// 以二进制字符串的形式读取本地文件
fileReader.readAsBinaryString(file);
// 阻止Upload组件的上传逻辑
return false;
}
文件转换
由于XLSX.utils.sheet_to_json读取文件后的格式与Table组件所需的dataSource格式不一样,需要进行转换
const dataToDatasource = (data) => {
const list = [];
data.forEach((row) => {
const obj = {};
Object.entries(row).forEach(([key, value]) => {
obj[key] = value;
})
list.push(getDataIndexByTitle(obj, columns))
})
return list
}
效果图
实现导出xlsx
-
创建excel文件对象
-
将dataSource转换为xlsx包所需的格式
-
创建sheet对象
-
将sheet添加到xlsx对象中
-
写入文件
const exportXlsx = () => {
var workbook = XLSX.utils.book_new();
// // 将数据转换为xlsx包所需格式
const data = dataSourceToData(dataSource, columns)
var worksheet = XLSX.utils.aoa_to_sheet(data);
XLSX.utils.book_append_sheet(workbook, worksheet, "page1");
XLSX.writeFile(workbook, "file5.xlsx", { bookType: "xlsx" });
}
文件转换
由于XLSX.utils.aoa_to_sheet需要的文件格式与dataSource格式不一样,需要进行转换
const dataSourceToData = (ds, cols) => {
const columns = cols.map(item => item.dataIndex);
const list = [];
const tHead = cols.map(item => item.title);
list.push(tHead);
ds.forEach(d => {
const row = []
columns.forEach(c => {
row.push(d[c])
})
list.push(row)
})
return list
}
效果图
点赞收藏不迷路