自从用了 EasyExcel,导入导出 Excel 更简单了! 您所在的位置:网站首页 excel表格直接导入数据 自从用了 EasyExcel,导入导出 Excel 更简单了!

自从用了 EasyExcel,导入导出 Excel 更简单了!

2023-06-07 19:25| 来源: 网络整理| 查看: 265

EasyExcel

在做excel导入导出的时候,发现项目中封装的工具类及其难用,于是去gitHub上找了一些相关的框架,最终选定了EasyExcel。之前早有听闻该框架,但是一直没有去了解,这次借此学习一波,提高以后的工作效率。

实际使用中,发现是真的很easy,大部分api通过名称就能知道大致意思,这点做的很nice。参考文档,大部分场景的需求基本都能够满足。

GitHub上的官方说明

快速开始 maven仓库地址     com.alibaba     easyexcel     2.1.2 导入 如下图excel表格:

建立导入对应实体类 @Data public class ReqCustomerDailyImport {     /**      * 客户名称      */     @ExcelProperty(index = 0)     private String customerName;     /**      * MIS编码      */     @ExcelProperty(index = 1)     private String misCode;     /**      * 月度滚动额      */     @ExcelProperty(index = 3)     private BigDecimal monthlyQuota;     /**      * 最新应收账款余额      */     @ExcelProperty(index = 4)     private BigDecimal accountReceivableQuota;     /**      * 本月利率(年化)      */     @ExcelProperty(index = 5)     private BigDecimal dailyInterestRate; } Controller代码 @PostMapping("/import") public void importCustomerDaily(@RequestParam MultipartFile file) throws IOException {     InputStream inputStream = file.getInputStream();     List reqCustomerDailyImports = EasyExcel.read(inputStream)             .head(ReqCustomerDailyImport.class)             // 设置sheet,默认读取第一个             .sheet()             // 设置标题所在行数             .headRowNumber(2)             .doReadSync(); } 运行结果

可以看出只需要在实体对象使用@ExcelProperty注解,读取时指定该class,即可读取,并且自动过滤了空行,对于excel的读取及其简单。

不过此时发现一个问题,这样我如果要校验字段该怎么办?要将字段类型转换成另外一个类型呢?

不必担心,我们可以想到的问题,作者肯定也考虑到了,下面来一个Demo。

代码如下 List reqCustomerDailyImports = EasyExcel.read(inputStream) // 这个转换是成全局的, 所有java为string,excel为string的都会用这个转换器。 // 如果就想单个字段使用请使用@ExcelProperty 指定converter .registerConverter(new StringConverter()) // 注册监听器,可以在这里校验字段 .registerReadListener(new CustomerDailyImportListener()) .head(ReqCustomerDailyImport.class) .sheet() .headRowNumber(2) .doReadSync(); } 监听器 public class CustomerDailyImportListener extends AnalysisEventListener { List misCodes = Lists.newArrayList(); /** * 每解析一行,回调该方法 * @param data * @param context */ @Override public void invoke(Object data, AnalysisContext context) { String misCode = ((ReqCustomerDailyImport) data).getMisCode(); if (StringUtils.isEmpty(misCode)) { throw new RuntimeException(String.format("第%s行MIS编码为空,请核实", context.readRowHolder().getRowIndex() + 1)); } if (misCodes.contains(misCodes)) { throw new RuntimeException(String.format("第%s行MIS编码已重复,请核实", context.readRowHolder().getRowIndex() + 1)); } else { misCodes.add(misCode); } } /** * 出现异常回调 * @param exception * @param context * @throws Exception */ @Override public void onException(Exception exception, AnalysisContext context) throws Exception { // ExcelDataConvertException:当数据转换异常的时候,会抛出该异常,此处可以得知第几行,第几列的数据 if (exception instanceof ExcelDataConvertException) { Integer columnIndex = ((ExcelDataConvertException) exception).getColumnIndex() + 1; Integer rowIndex = ((ExcelDataConvertException) exception).getRowIndex() + 1; String message = "第" + rowIndex + "行,第" + columnIndex + "列" + "数据格式有误,请核实"; throw new RuntimeException(message); } else if (exception instanceof RuntimeException) { throw exception; } else { super.onException(exception, context); } } /** * 解析完全部回调 * @param context */ @Override public void doAfterAllAnalysed(AnalysisContext context) { misCodes.clear(); } } 转换器 public class StringConverter implements Converter { @Override public Class supportJavaTypeKey() { return String.class; } @Override public CellDataTypeEnum supportExcelTypeKey() { return CellDataTypeEnum.STRING; } /** * 将excel对象转成Java对象,这里读的时候会调用 * * @param cellData NotNull * @param contentProperty Nullable * @param globalConfiguration NotNull * @return */ @Override public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return "自定义:" + cellData.getStringValue(); } /** * 将Java对象转成String对象,写出的时候调用 * * @param value * @param contentProperty * @param globalConfiguration * @return */ @Override public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return new CellData(value); }

可以看出注册了一个监听器:CustomerDailyImportListener,还注册了一个转换器:StringConverter。流程为:框架读取一行数据,先执行转换器,当一行数据转换完成,执行监听器的回调方法,如果转换的过程中,出现转换异常,也会回调监听器中的onException方法。因此,可以在监听器中校验数据,在转换器中转换数据类型或者格式。

运行结果

修改一下表格,测试校验是否生效

再次导入,查看运行结果

导入相关常用API

注解

ExcelProperty 指定当前字段对应excel中的那一列。可以根据名字或者Index去匹配。当然也可以不写,默认第一个字段就是index=0,以此类推。千万注意,要么全部不写,要么全部用index,要么全部用名字去匹配。千万别三个混着用,除非你非常了解源代码中三个混着用怎么去排序的。

ExcelIgnore 默认所有字段都会和excel去匹配,加了这个注解会忽略该字段。

DateTimeFormat 日期转换,用String去接收excel日期格式的数据会调用这个注解。里面的value参照java.text.SimpleDateFormat。

NumberFormat 数字转换,用String去接收excel数字格式的数据会调用这个注解。里面的value参照java.text.DecimalFormat。

EasyExcel相关参数

readListener 监听器,在读取数据的过程中会不断的调用监听器。

converter 转换器,默认加载了很多转换器。也可以自定义,如果使用的是registerConverter,那么该转换器是全局的,如果要对单个字段生效,可以在ExcelProperty注解的converter指定转换器。

headRowNumber 需要读的表格有几行头数据。默认有一行头,也就是认为第二行开始起为数据。

head 与clazz二选一。读取文件头对应的列表,会根据列表匹配数据,建议使用class。

autoTrim 字符串、表头等数据自动trim。

sheetNo 需要读取Sheet的编码,建议使用这个来指定读取哪个Sheet。

sheetName 根据名字去匹配Sheet,excel 2003不支持根据名字去匹配。

导出 建立导出对应实体类 @Data public class ReqCustomerDailyImport { /** * 客户名称 */ @ExcelProperty(index = 0) private String customerName; /** * MIS编码 */ @ExcelProperty(index = 1) private String misCode; /** * 月度滚动额 */ @ExcelProperty(index = 3) private BigDecimal monthlyQuota; /** * 最新应收账款余额 */ @ExcelProperty(index = 4) private BigDecimal accountReceivableQuota; /** * 本月利率(年化) */ @ExcelProperty(index = 5) private BigDecimal dailyInterestRate; } Controller代码 @PostMapping("/import") public void importCustomerDaily(@RequestParam MultipartFile file) throws IOException {     InputStream inputStream = file.getInputStream();     List reqCustomerDailyImports = EasyExcel.read(inputStream)             .head(ReqCustomerDailyImport.class)             // 设置sheet,默认读取第一个             .sheet()             // 设置标题所在行数             .headRowNumber(2)             .doReadSync(); } 导出效果

导出相关常用API

注解

ExcelProperty 指定写到第几列,默认根据成员变量排序。value指定写入的名称,默认成员变量的名字。

ExcelIgnore 默认所有字段都会写入excel,这个注解会忽略这个字段。

DateTimeFormat 日期转换,将Date写到excel会调用这个注解。里面的value参照java.text.SimpleDateFormat。

NumberFormat 数字转换,用Number写excel会调用这个注解。里面的value参照java.text.DecimalFormat。

EasyExcel相关参数

needHead 监听器是否导出头。

useDefaultStyle 写的时候是否是使用默认头。

head 与clazz二选一。写入文件的头列表,建议使用class。

autoTrim 字符串、表头等数据自动trim。

sheetNo 需要写入的编码。默认0。

sheetName 需要些的Sheet名称,默认同sheetNo。

总结

可以看出不管是excel的读取还是写入,都是一个注解加上一行代码完成,可以让我们少些很多解析的代码,极大减少了重复的工作量。当然这两个例子使用了最简单的方式,EasyExcel还支持更多场景,例如读,可以读多个sheet,也可以解析一行数据或者多行数据做一次入库操作;写的话,支持复杂头,指定列写入,重复多次写入,多个sheet写入,根据模板写入等等



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有