给我实现一个前端的 Excel 导入和导出功能

本文介绍了如何在前端使用`xlsx`库实现Excel的导入和导出功能。首先,通过`FileReader`读取Excel文件并用`XLSX`库解析为JSON。接着,展示了读取文件的代码和导出数据的方法。文章强调了前端处理导入导出的效率优势,并提示注意批量操作的耗时问题,可以使用异步处理。此外,还提供了有表格样式的导出解决方案。

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

前言

负责人 A】:现在报表部分基于接口的 Excel 的导入和导出功能有点慢,前端这边能不能实现一下这个功能,然后我们在比对看看效果!

切图仔 B】: 接口这边不能优化一下吗?比如排查下慢的原因什么的。

负责人 A】:现在后端开发任务比较重,处理的核心任务也多还会涉及一些架构上的调整,所以想着前端这边可以处理一下,然后看看整体效果。

切图仔 B】: OK,试试 就 ~ Shi Shi ~

下面就基于 xlsx 这个第三方库封装一个 <ExcelUpload /> 组件实现表格导入,以及 json 数据导出 Excel 功能的 json2Excel() 工具方法。

选择 xlsx 的原因如下图所示:

Excel 解析为 JSON

基本内容

组件效果和结构

组件内容是很简单的结构和视图,直接查看如下的页面效果和代码即可:


### Excel 数据格式

**`Excel`** 数据格式有两种,一种是 **有表头说明** 的,另一种是 **无表头说明** 的,具体内容如下:

* **有表头说明**<img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7ae907cd0b6f461da9560e4fca1ec32e~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?" style="margin: auto" />
* **无表头说明**<img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/320d6d696370430eb49e0d6b6e7f2c15~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?" style="margin: auto" />

实现 Excel 转 JSON 功能
------------------

### 核心步骤

* 通过 `FileReader` 以二进制的方式读取 `Excel` 文件,即 `fileReader.readAsBinaryString(file)`* 将对应的二进制数据通过 `XLSX.read(fileData, { type: "binary" })` 方法生成 `workbook` 对象* `workbook.SheetNames[0]` 获取第一个 `Sheet` 的名称 `wsname`,因为表格是有序列表,因此可以有多个 `Sheet`<img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b212194acd2845c885764ebdcf15fda2~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?)* 通过 `XLSX.utils.sheet_to_json(workbook.Sheets[wsname])` 方法将对应的 `Sheet` 内容转换为 `JSON` 数据### 效果演" style="margin: auto" />

* **有表头说明**<img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/17bb66e17cba4018a8fd097accf6f352~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?) ![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3064b64aa0134d85ae2c66550fb72e00~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?" style="margin: auto" />
* **无表头说明**<img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/72fd47c5d82b4efb936f5b9f98486440~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?) ![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/93c709390f1f4d339a259dbc46dce83d~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?" style="margin: auto" />

### 具体代码

// 读取对应表格文件
const readerExcel = (file: File) => {const fileReader = new FileReader();// 以二进制的方式读取表格内容fileReader.readAsBinaryString(file);// 表格内容读取完成fileReader.onload = (event: any) => {try {const fileData = event.target.result;const workbook = XLSX.read(fileData, {type: “binary”,});// 表格是有序列表,因此可以取多个 Sheet,这里取第一个 Sheetconst wsname = workbook.SheetNames[0];// 将表格内容生成 json 数据const sheetJson = XLSX.utils.sheet_to_json(workbook.Sheets[wsname]);console.log(sheetJson); // 得到的表格 JSON 内容} catch (e) {console.log(e);return false;}};
};

// 文件变化时触发
const onChange = (event) => {// 获取文件对象const file = event.target.files[0];// 读取文件内容readerExcel(file);// 清除数据clearFile();
};

const clearFile = () => {excelRef.value.value = “”;
};


格式化 JSON 数据
-----------

这里需要考虑 **有表头说明** 和 **无表头说明** 的情况,为了方便统一处理,作如下规定:

* 通过将 **有表头说明** 的数据格式统一转化为 **无表头说明** 的数据格式
* 统一将 **无表头说明** 的数据格式转化为标准的接口入参,即 `{ key: value }`,这里需要建立一个 `name -> key` 的映射关系:```const excelNameToKey = {'姓名': "name",'年龄': "age",'特长': "skill",'电话': "telephone",'地址': "address",}; ```**格式化如下:**

<img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/31ff6d40f6984d1e85a64854dfb18d45~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?" style="margin: auto" />

**核心代码如下:**


JSON 导出为 Excel
==============

基本结构
----

页面内容也非常简单,具体如下:

<img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ca0648a760bb4834a6e1cee3ba03f38a~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?)``" style="margin: auto" />
<template><div id="container"><h1>JSON 数据:</h1><h2><code>{{ jsonData }}</code></h2><button @click="exportExcel">导出 Excel</button></div>
</template> 

导出功能

导出其实也很简单,首先创建 src/utils/json2Excel.ts 文件里面就是具体导出的实现,具体内容如下:

// src/utils/json2Excel.ts

import * as XLSX from "xlsx";

export default (data: any[],sheetName: string = "sheet1",fileName: string = "json2Excel.xlsx"
) => {const jsonWorkSheet = XLSX.utils.json_to_sheet(data);const workBook = {SheetNames: [sheetName], // 指定有序 sheet 的 nameSheets: {[sheetName]: jsonWorkSheet, // 表格数据内容},};return XLSX.writeFile(workBook, fileName); // 向文件系统写出文件
}; 

然后在 App.vue 中使用,具体如下:

// src/App.vue

<script setup lang="ts">

import json2Excel from "./utils/json2Excel";

// 测试的 JSON 数据
const jsonData = [{name: "张三1",age: 18,skill: "干饭1",telephone: 20200825,address: "宇宙尽头1",},{name: "张三2",age: 19,skill: "干饭2",telephone: 20200826,address: "宇宙尽头2",},{name: "张三3",age: 20,skill: "干饭3",telephone: 20200827,address: "宇宙尽头3",},{name: "张三4",age: 21,skill: "干饭4",telephone: 20200828,address: "宇宙尽头4",},{name: "张三5",age: 22,skill: "干饭5",telephone: 20200829,address: "宇宙尽头5",},{name: "张三6",age: 23,skill: "干饭6",telephone: 20200830,address: "宇宙尽头6",},{name: "张三7",age: 24,skill: "干饭7",telephone: 20200831,address: "宇宙尽头7",},{name: "张三8",age: 25,skill: "干饭8",telephone: 20200832,address: "宇宙尽头8",},{name: "张三9",age: 26,skill: "干饭9",telephone: 20200833,address: "宇宙尽头9",},{name: "张三10",age: 27,skill: "干饭10",telephone: 20200834,address: "宇宙尽头10",},
];

// key -> name 的映射
const excelKeyToName = {name: "姓名",age: "年龄",skill: "特长",telephone: "电话",address: "地址",
};

// 导出 Excel 文件
const exportExcel = () => {// 格式化参数const data = jsonData.map((item) => {const newItem: any = {};Object.keys(item).forEach(key => {newItem[excelKeyToName[key]] = item[key];});return newItem;});
 // 导出 Exceljson2Excel(data);
};
</script> 

效果演示

最后

以上只是实现了简单的单个导入、导出功能,可以将其完善为 批量操作,但是要注意批量操作带来的耗时性,将对应的耗时部分通过 webworker 等方式处理,这样页面就不需要一直等待当前的操作完成。

另外,如果有要求在导出 Excel 时有表格样式(如:行列宽高设置等)可以通过 xlsx-populate 来实现。

以上就是本文的全部内容,希望上述内容可以给大家带来一些思路,可以在评论区贡献更优质的方案。

最后

为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值