1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 可以实现一个前端的 Excel 导入和导出功能吗?

可以实现一个前端的 Excel 导入和导出功能吗?

时间:2023-06-22 21:28:25

相关推荐

可以实现一个前端的 Excel 导入和导出功能吗?

点击上方前端Q,关注公众号

回复加群,加入前端Q技术交流

前言

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

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

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

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

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

选择 **`xlsx`**[3] 的原因如下图所示:

Excel 解析为 JSON

基本内容

组件效果和结构

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

<template><inputtype="file"ref="excelRef":accept="props.accept"@change="onChange"class="excel"/><h1>解析数据:</h1><h2><code>{{excelData}}</code></h2></template><scriptsetuplang="ts">import{reactive,ref}from'vue'import*asXLSXfrom'xlsx'interfaceProps{accept:string}constprops=withDefaults(defineProps<Props>(),{accept:'.csv,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',})constexcelRef:any=ref(null)constexcelData:any[]=reactive([])constonChange=(event:any)=>{//获取文件对象constfile=event.target.files[0]console.log(file)}</script>复制代码

Excel 数据格式

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

有表头说明

无表头说明

实现 Excel 转 JSON 功能

核心步骤

通过FileReader以二进制的方式读取Excel文件,即fileReader.readAsBinaryString(file)

将对应的二进制数据通过XLSX.read(fileData, { type: "binary" })方法生成workbook对象

workbook.SheetNames[0]获取第一个Sheet的名称wsname,因为表格是有序列表,因此可以有多个Sheet

image.png

通过XLSX.utils.sheet_to_json(workbook.Sheets[wsname])方法将对应的Sheet内容转换为JSON数据

效果演示

有表头说明

无表头说明

具体代码

//读取对应表格文件constreaderExcel=(file:File)=>{constfileReader=newFileReader();//以二进制的方式读取表格内容fileReader.readAsBinaryString(file);//表格内容读取完成fileReader.onload=(event:any)=>{try{constfileData=event.target.result;constworkbook=XLSX.read(fileData,{type:"binary",});//表格是有序列表,因此可以取多个Sheet,这里取第一个Sheetconstwsname=workbook.SheetNames[0];//将表格内容生成json数据constsheetJson=XLSX.utils.sheet_to_json(workbook.Sheets[wsname]);console.log(sheetJson);//得到的表格JSON内容}catch(e){console.log(e);returnfalse;}};};//文件变化时触发constonChange=(event)=>{//获取文件对象constfile=event.target.files[0];//读取文件内容readerExcel(file);//清除数据clearFile();};constclearFile=()=>{excelRef.value.value="";};复制代码

格式化 JSON 数据

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

通过将有表头说明的数据格式统一转化为无表头说明的数据格式

统一将无表头说明的数据格式转化为标准的接口入参,即{ key: value },这里需要建立一个name -> key的映射关系:

constexcelNameToKey={'姓名':"name",'年龄':"age",'特长':"skill",'电话':"telephone",'地址':"address",};复制代码

格式化如下:

核心代码如下:

<scriptsetuplang='ts'>import{reactive,ref}from"vue";import*asXLSXfrom"xlsx";constexcelNameToKey={姓名:"name",年龄:"age",特长:"skill",电话:"telephone",地址:"address",};interfaceProps{accept:string;}constprops=withDefaults(defineProps<Props>(),{accept:".csv,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",});constexcelRef:any=ref(null);constexcelData:any[]=reactive([]);constclearFile=()=>{excelRef.value.value="";};//标准化JSON数据constexcelDataToJson=(sheetJson:any[])=>{if(!sheetJson.length)return;letresult=sheetJson;consthasTableHead=!!sheetJson[0].__EMPTY;//拥有表头的数据,需要取正确的值if(hasTableHead){constheader=sheetJson.shift();constdata:any[]=[];Object.keys(header).forEach((key)=>{sheetJson.forEach((item,index)=>{constobj=data[index]||{};obj[header[key]]=item[key];data[index]=obj;});});console.log("【】【】",data);result=data;}//将表格对应的文字转换为keyresult.forEach((item)=>{constnewItem:any={};Object.keys(item).forEach((key)=>{newItem.title=key;newItem[excelNameToKey[key]]=item[key];});excelData.push(newItem);});};//读取对应表格文件constreaderExcel=(file:File)=>{constfileReader=newFileReader();//以二进制的方式读取表格内容fileReader.readAsBinaryString(file);//表格内容读取完成fileReader.onload=(event:any)=>{try{constfileData=event.target.result;constworkbook=XLSX.read(fileData,{type:"binary",});//表格是有序列表,因此可以取多个Sheet,这里取第一个Sheetconstwsname=workbook.SheetNames[0];//将表格内容生成json数据constsheetJson=XLSX.utils.sheet_to_json(workbook.Sheets[wsname]);console.log(sheetJson);//标准化JSON数据excelDataToJson(sheetJson);}catch(e){console.log(e);returnfalse;}};};//文件变化时触发constonChange=(event)=>{//获取文件对象constfile=event.target.files[0];//读取文件内容readerExcel(file);//清除数据clearFile();};</script>复制代码

JSON 导出为 Excel

基本结构

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

<template><divid="container"><h1>JSON 数据:</h1><h2><code>{{jsonData}}</code></h2><button@click="exportExcel">导出Excel</button></div></template>复制代码

导出功能

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

//src/utils/json2Excel.tsimport*asXLSXfrom"xlsx";exportdefault(data:any[],sheetName:string="sheet1",fileName:string="json2Excel.xlsx")=>{constjsonWorkSheet=XLSX.utils.json_to_sheet(data);constworkBook={SheetNames:[sheetName],//指定有序sheet的nameSheets:{[sheetName]:jsonWorkSheet,//表格数据内容},};returnXLSX.writeFile(workBook,fileName);//向文件系统写出文件};复制代码

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

//src/App.vue<scriptsetuplang="ts">importjson2Excelfrom"./utils/json2Excel";//测试的JSON数据constjsonData=[{name:"张三1",age:18,skill:"干饭1",telephone:2025,address:"宇宙尽头1",},{name:"张三2",age:19,skill:"干饭2",telephone:2026,address:"宇宙尽头2",},{name:"张三3",age:20,skill:"干饭3",telephone:2027,address:"宇宙尽头3",},{name:"张三4",age:21,skill:"干饭4",telephone:2028,address:"宇宙尽头4",},{name:"张三5",age:22,skill:"干饭5",telephone:2029,address:"宇宙尽头5",},{name:"张三6",age:23,skill:"干饭6",telephone:2030,address:"宇宙尽头6",},{name:"张三7",age:24,skill:"干饭7",telephone:2031,address:"宇宙尽头7",},{name:"张三8",age:25,skill:"干饭8",telephone:2032,address:"宇宙尽头8",},{name:"张三9",age:26,skill:"干饭9",telephone:2033,address:"宇宙尽头9",},{name:"张三10",age:27,skill:"干饭10",telephone:2034,address:"宇宙尽头10",},];//key->name的映射constexcelKeyToName={name:"姓名",age:"年龄",skill:"特长",telephone:"电话",address:"地址",};//导出Excel文件constexportExcel=()=>{//格式化参数constdata=jsonData.map((item)=>{constnewItem:any={};Object.keys(item).forEach(key=>{newItem[excelKeyToName[key]]=item[key];});returnnewItem;});//导出Exceljson2Excel(data);};</script>复制代码

效果演示

最后

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

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

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

关于本文

作者:熊的猫

/post/7135945969425711111

往期推荐

前端架构带你 封装axios,一次封装终身受益「美团后端连连点赞」

5 种瀑布流场景的实现原理解析

纯前端实现「羊了个羊」小游戏

最后

欢迎加我微信,拉你进技术群,长期交流学习...

欢迎关注「前端Q」,认真学前端,做个专业的技术人...

点个在看支持我吧

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。