因为是第一次实现这样的功能,先在网上进行了查找,发现了三种比较常用的方法:1.安装file-saverxlsxscript-loader如果想设置表格样式的话,需要同时安装依赖xlsx-style,通常情况下安装此依赖会报错,需要进行修改;2.安装vue-json-excel这个插件看起来比较好上手,但是好像只适用于导出简单表头,不支持多级,如果导出表格简单的话大家可以尝试一下。不过因为不符合我的需求,所以我直接跳过了,不知道是否可以设置样式;3.安装exceljs只用安装一个依赖并且支持修改样式,我选择了这个方法。
npminstallexceljs
表格数据包含了表头标题和表里内容,需要处理成固定格式。请求后端拿到的表格数据格式:
需要拿到的表头数据格式:
[{name:"name",label:"名称"},{name:"",label:"价格指数",children:[{name:"",label:"2023年",children:[{name:"price1",label:"1月"},{name:"price2",label:"2月"}]}]}]其中name为绑定的字段,类似于table表格中的prop;label为name对应的字段名称,类似于table表格中的label。需要注意的是,导出表格和页面展示不一样,页面展示的时候prop值我们可以使用a.b或者a[0].b展示,但是导出的时候name值不可以,必须使用单个字段。
需要拿到的表中数据格式:可以直接为请求后端拿到的表格数据,如果有需要处理的数据进行处理即可。我请求到的数据中有三类数据需要进行处理。第一种是返回为字典key,需要转换成字典value值;第二种是返回数据格式为list,需要转换成单个的数据;第三种是对象数据,取出其中的值
letlist=data.map(item=>{//一个一个判断然后处理就可以,不要嫌麻烦//字典转换for(letkeyinitem){if(key=="status"{item[key]=this.selectDictLabel(this.yesOrNo,item[key]);}}//list拆解for(leti=0;i<12;i++){item["price"+i]=item.priceIndexList[i].indexValue;}//对象取值item.staff=item.staffIndexitem.staffIndex.indexValue:"";})不要嫌麻烦,前端实现导出本来就是一件麻烦的事情。
this.exportMultiHeaderExcel(title,list);//title为设置好的表头数据,list为表中数据导出方法中判断表头有几行,合并单元格由于导出方法过长,所以对代码块进行了分割,其实都在这个方法中
exportMultiHeaderExcel(column,data){letkeyArr=this.columns.map((item)=>{returnitem.label;})//一级表头数组letsingleLen=keyArr.length;//简单标题长度letmultiLen=0;//用来判断是否有三级表头letdoubLen=0;//用来判断是否有二级表头letrow1=JSON.parse(JSON.stringify(keyArr));letidx1=row1.findIndex((item)=>item=="价格指数");if(idx1>-1){row1.splice(idx1+1,0,"","","","","","","","","","","");singleLen--;multiLen++;}letidx6=row1.findIndex((item)=>item=="期末人数");if(idx6>-1){singleLen--;doubLen=1;}letrow2=[];letrow3=[];},导出方法中判断表头有几行,合并单元格由于导出方法过长,所以对代码块进行了分割,其实都在这个方法中
exportMultiHeaderExcel(column,data){letkeyArr=this.columns.map((item)=>{returnitem.label;})//一级表头数组letsingleLen=keyArr.length;//简单标题长度letmultiLen=0;//用来判断是否有三级表头letdoubLen=0;//用来判断是否有二级表头letrow1=JSON.parse(JSON.stringify(keyArr));letidx1=row1.findIndex((item)=>item=="价格指数");if(idx1>-1){row1.splice(idx1+1,0,"","","","","","","","","","","");singleLen--;multiLen++;}letidx6=row1.findIndex((item)=>item=="期末人数");if(idx6>-1){singleLen--;doubLen=1;}letrow2=[];letrow3=[];},导出方法中不同标题处理每一行必须保持相同的长度,为了之后合并单元格,没有数据的设置为空
//判断不同标题进行不同处理if(multiLen&&doubLen){//所有标题都有for(leti=0;i
导出方法中创建工作表
//创建excelconstworkbook=newExcelJS.Workbook();//创建工作表constsheet=workbook.addWorksheet("sheet1");//添加表头sheet.getRow(1).values=row1;if(row2&&row2.length){sheet.getRow(2).values=row2;}if(row3&&row3.length){sheet.getRow(3).values=row3;}
导出方法中导出表头设置因为我这只有三级标题所以进行了三次循环,循环次数和标题行数有关系,这里应该可以简化,还没想到具体方法
//表格样式for(leti=0;i 导出方法中写入文件 autoWidthAction(val,width){if(val==null){width=10;}elseif(val.toString().charCodeAt(0)>255){/*ifchinese*/width=val.toString().length*2;}else{width=val.toString().length;}returnwidth}