作者:风雨\来源:jianshu.com/p/8f3defdc76d4EasyExcel做excel导入导出,发现项目中打包的工具极其难用,于是去gitHub找了一些相关的框架,最后选择了OrderedEasyExcel。之前听说过这个框架,但是一直没搞懂。这次吸取教训,提高自己以后的工作效率。在实际使用中,真的很容易发现,大部分API都能通过名字知道大概的意思,非常nice。参考文档,基本可以满足大部分场景的需求。GitHub官方说明快速启动maven仓库地址com.alibabaeasyexcel2.1.2推荐一个开源的并且免费SpringBoot最全教程:https://github.com/javastacks/spring-boot-best-practice导入excel表格如下图:创建并导入对应的实体类@DatapublicclassReqCustomerDailyImport{/***客户名称*/@ExcelProperty(index=0)privateStringcustomerName;/***MIS代码*/@ExcelProperty(index=1)privateStringmisCode;/***每月滚动配额*/@ExcelProperty(index=3)privateBigDecimalmonthlyQuota;/***最新应收账款余额*/@ExcelProperty(index=4)privateBigDecimalaccountReceivableQuota;/***本月利率(年化)*/@ExcelProperty(index=5)privateBigDecimaldailyInterestRate;}Controllercode@PostMapping("/import")publicvoidimportCustomerDaily(@RequestParamMultipartFilefile)throwsIOException{InputStreaminputStream=file.getInputStream();ListreqCustomerDailyImports=EasyExcel.read(inputStream).head(ReqCustomerDailyImport.class)//设置sheet,默认读取第一个。sheet()//设置标题所在的行数。headRowNumber(2).doReadSync();}运行结果表明,只需要在实体对象上使用@ExcelProperty注解,读取时指定类,即可读取,自动过滤空行。对于excel的读取和很简单,但是这个时候我发现了一个问题,那么要验证字段怎么办呢?将字段类型转换为另一种类型怎么样?不用着急,作者肯定已经考虑到了我们能想到的问题,这里有一个demo代码如下string将使用此转换器。//如果要使用单个字段,请使用@ExcelProperty指定转换器。registerConverter(newStringConverter())//注册监听器,这里可以查看字段。registerReadListener(newCustomerDailyImportListener()).head(ReqCustomerDailyImport.class)。sheet().headRowNumber(2).doReadSync();}ListenerpublicclassCustomerDailyImportListenerextendsAnalysisEventListener{ListmisCodes=Lists.newArrayList();/***为解析的每一行回调此方法*@paramdata*@paramcontext*/@Overridepublicvoidinvoke(Objectdata,AnalysisContextcontext){StringmisCode=((ReqCustomerDailyImport)data).getMisCode();if(StringUtils.isEmpty(misCode)){thrownewRuntimeException(String.format("第s行的%MIS代码为空,请验证",context.readRowHolder().getRowIndex()+1));}if(misCodes.contains(misCodes)){thrownewRuntimeException(String.format("%s行MIS编码重复,请验证",context.readRowHolder().getRowIndex()+1));}else{misCodes.add(misCode);}}/***异常回调*@paramexception*@paramcontext*@throwsException*/@OverridepublicvoidonException(Exceptionexception,AnalysisContextcontext)throwsException{//ExcelDataConvertException:当数据转换异常时,抛出该异常会抛出,这里可以知道数据的行列if(exceptioninstanceofExcelDataConvertException){IntegercolumnIndex=((ExcelDataConvertException)exception).getColumnIndex()+1;整数rowIndex=((ExcelDataConvertException)exception).getRowIndex()+1;Stringmessage="th"+rowIndex+"row,"+columnIndex+"Column"+"数据格式错误,请验证";抛出新的RuntimeException(消息);}elseif(exceptioninstanceofRuntimeException){抛出异常;}else{super.onException(异常,上下文);}}/***分析后的所有回调*@paramcontext*/@OverridepublicvoiddoAfterAllAnalysed(AnalysisContextcontext){misCodes.clear();}}转换器publicclassStringConverterimplementsConverter{@OverridepublicClasssupportJavaTypeKey(){returnString.class;}@OverridepublicCellDataTypeEnumsupportExcelTypeKey(){returnCellDataTypeEnum.STRING;}/***将excel对象转换为Java对象,这里读取时会调用**@paramcellDataNotNull*@paramcontentPropertyNullable*@paramglobalConfigurationNotNull*@return*/@OverridepublicStringconvertToJavaData(CellDatacellData,ExcelContentPropertycontentProperty,GlobalConfigurationglobalConfiguration){return"Custom:"+cellData.getStringValue();}/***将Java对象转换成String对象,写的时候调用**@paramvalue*@paramcontentProperty*@paramglobalConfiguration*@return*/@OverridepublicCellDataconvertToExcelData(Stringvalue,ExcelContentPropertycontentProperty,GlobalConfigurationglobalConfiguration){returnnewCellData(value);}}可以看出,注册了一个监听器:CustomerDailyImportListener,同时注册了一个转换转换器:StringConverter的过程是:框架读取一行数据,先执行转换器,当调用完成时执行监听器的回调方法一行数据转换完成。如果在转换过程中出现转换异常,监听器中的onException方法也会被回调。因此,可以在监听器中验证数据,并在转换器中转换数据类型或格式。运行结果,修改表,测试验证是否有效再导入,检查运行结果,导入相关的常用API注解。ExcelProperty指定当前字段对应的excel中的列。您可以按名称或索引进行匹配。当然,你也可以留空。默认第一个字段是index=0,依此类推。注意,要么不全部写,要么全部用索引,要么全部用名字来匹配。三者不要混用,除非你非常清楚源码中如何对三者进行排序。ExcelIgnore默认情况下,所有字段都会匹配excel,添加这个注解会忽略这个字段。DateTimeFormat日期转换,使用String接收excel日期格式的数据会调用该注解。里面的值是指java.text.SimpleDateFormat。NumberFormat数字转换,使用String接收excel数字格式数据会调用这个注解。里面的值是指java.text.DecimalFormat。EasyExcel相关参数readListener监听器,在读取数据的过程中会不断调用监听器。converter转换器,默认加载了很多转换器。它也可以定制。如果您使用registerConverter,则转换器是全局的。如果要对单个字段生效,可以在ExcelProperty注解的转换器中指定转换器。headRowNumber要读取的表有几行表头数据。默认有行表头,即第二行被认为是数据。选择head和clazz之一。读取文件头对应的列表,根据列表匹配数据。建议使用类。autoTrim自动修剪字符串和表头等数据。sheetNo需要读取Sheet的编码,推荐使用这个来指定读取哪个Sheet。sheetName按名称匹配Sheet,excel2003不支持按名称匹配。Export创建并导出对应的实体类@Data@BuilderpublicclassRespCustomerDailyImport{@ExcelProperty("Customercode")privateStringcustomerName;@ExcelProperty("MIS代码")privateStringmisCode;@ExcelProperty("每月滚动金额")privateBigDecimalmonthlyQuota;@ExcelProperty("最新的应收账款余额")privateBigDecimalaccountReceivableQuota;@NumberFormat("#.##%")@ExcelProperty("本月利率(年化)")privateBigDecimaldailyInterestRate;}Controllercode@GetMapping("/export")publicvoidexport(HttpServletResponseresponse)throwsIOException{//生成数据ListrespCustomerDailyImports=Lists.newArrayList();对于(inti=0;i<50;i++){RespCustomerImportrespCustomerDailyImport=DeliveryCustomerDailyImportbuilder().misCode(String.valueOf(i)).customerName("customerName"+i).monthlyQuota(newBigDecimal(String.valueOf(i))).accountReceivableQuota(newBigDecimal(String.valueOf(i))).dailyInterestRate(newBigDecimal(String.valueOf(i))).build();respCustomerDailyImports.add(respCustomerDailyImport);}响应.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");//这里的URLEncoder.encode可以防止中文乱码,当然和easyexcel无关StringfileName=URLEncoder.encode("export","UTF-8");response.setHeader("Content-disposition","attachment;filename="+fileName+".xlsx");EasyExcel.write(response.getOutputStream(),RespCustomerDailyImport.class).sheet("sheet0")//设置字段宽度自动调整,不是很精确。registerWriteHandler(newLongestMatchColumnWidthStyleStrategy()).doWrite(respCustomerDailyImports);}导出效果导出相关常用API注解ExcelProperty指定写入列,默认根据成员变量排序值指定写入名称,默认成员变量。ExcelIgnore默认所有字段都会写入excel,这个注解会忽略这个字段。DateTimeFormat日期转换,将Date写入excel会调用这个注解。里面的值是指java.text.SimpleDateFormat。NumberFormat数字转换,用Number写excel都会调用这个注解。里面的值是指java.text.DecimalFormat。EasyExcel相关参数needHead监听器是否导出表头。useDefaultStyle写入时是否使用默认表头。选择head和clazz之一。写文件的头列表,推荐使用class。autoTrim自动修剪字符串和表头等数据。sheetNo需要写编码。默认为0。sheetName必需工作表名称,默认与sheetNo相同。综上所述,可以看出无论是读还是写excel,都是一条注释一行代码完成,可以为我们节省大量的解析代码,大大减少重复的工作量。当然这两个例子用的是最简单的方法,EasyExcel还支持更多的场景,比如读取,可以读取多个sheet,也可以解析一行数据或者多行数据进行一次存储操作;写作方面,支持复杂表头、指定栏目写作、重复多次写作、多张写作、按模板写作等。近期热点文章推荐:1.1,000+Java面试题及答案(2022最新版)2.精彩!Java协程来了。..3.SpringBoot2.x教程,太全面了!4.不要用爆破爆满画面,试试装饰者模式,这才是优雅的方式!!5.《Java开发手册(嵩山版)》最新发布,赶快下载吧!感觉不错,别忘了点赞+转发!