EasyExcel

在做excel导入导出的时候,发现项目中封装的工具类及其难用,于是去gitHub上找了一些相关的框架,最终选定了EasyExcel。之前早有听闻该框架,但是一直没有去了解,这次借此学习一波,提高以后的工作效率。实际使用中,发现是真的很easy,大部分api通过名称就能知道大致意思,这点做的很nice。参考文档,大部分场景的需求基本都能够满足。

GitHub上的官方说明

image

快速开始

maven仓库地址

com.alibaba

easyexcel

2.1.2

导入

如下图excel表格:

image

建立导入对应实体类

@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();

}

运行结果

image

可以看出只需要在实体对象使用@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方法。因此,可以在监听器中校验数据,在转换器中转换数据类型或者格式。

运行结果

image

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

image

再次导入,查看运行结果

image

导入相关常用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

@Builder

public class RespCustomerDailyImport {

@ExcelProperty("客户编码")

private String customerName;

@ExcelProperty("MIS编码")

private String misCode;

@ExcelProperty("月度滚动额")

private BigDecimal monthlyQuota;

@ExcelProperty("最新应收账款余额")

private BigDecimal accountReceivableQuota;

@NumberFormat("#.##%")

@ExcelProperty("本月利率(年化)")

private BigDecimal dailyInterestRate;

}

Controller代码

@GetMapping("/export")

public void export(HttpServletResponse response) throws IOException {

// 生成数据

List respCustomerDailyImports = Lists.newArrayList();

for (int i = 0; i < 50; i++) {

RespCustomerDailyImport respCustomerDailyImport = RespCustomerDailyImport.builder()

.misCode(String.valueOf(i))

.customerName("customerName" + i)

.monthlyQuota(new BigDecimal(String.valueOf(i)))

.accountReceivableQuota(new BigDecimal(String.valueOf(i)))

.dailyInterestRate(new BigDecimal(String.valueOf(i))).build();

respCustomerDailyImports.add(respCustomerDailyImport);

}

response.setContentType("application/vnd.ms-excel");

response.setCharacterEncoding("utf-8");

// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系

String fileName = URLEncoder.encode("导出", "UTF-8");

response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");

EasyExcel.write(response.getOutputStream(), RespCustomerDailyImport.class)

.sheet("sheet0")

// 设置字段宽度为自动调整,不太精确

.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())

.doWrite(respCustomerDailyImports);

}

导出效果

image

导出相关常用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写入,根据模板写入等等。更多的例子可以去参考EasyExcel官方文档

easyexcel 在 设置标题_EasyExcel,让excel导入导出更加简单相关推荐

  1. easyexcel 设置标题_EasyExcel,让 excel 导入导出更加简单

    做积极的人,而不是积极废人! 来源:jianshu.com/p/8f3defdc76d4EasyExcelGitHub上的官方说明快速开始maven仓库地址导入导出总结 EasyExcel 在做exc ...

  2. easyexcel 在 设置标题_EasyExcel 自定义单元格式的问题。

    packagecom.kit;import--public classExcelKit {public static void parseExcelAndSave(ListapiStatusVOS,S ...

  3. SpringBoot中使用Easyexcel实现Excel导入导出功能(三)

    导出的数据包含有图片 导出excel表格的数据包含有图片,这种场景比较少.通Easyexcel实现这样的需求,我认为最简便的方法就是使用前面提到的自定义转换器(com.alibaba.excel.co ...

  4. SpringBoot中使用Easyexcel实现Excel导入导出功能(一)

    目录 前言 1.常规导入 2.读取到指定的列 3.读取全部的sheet页 4.日期.数字及其他自定义格式的转换 5.表头有多行的表格读取 6.表头数据的读取 7.单元格内的备注内容读取 前言 exce ...

  5. 注解+反射优雅的实现Excel导入导出(通用版)

    以下文章来源方志朋的博客,回复"666"获面试宝典 来源:blog.csdn.net/youzi1394046585/ article/details/86670203 日常在做后 ...

  6. 一个基于POI的通用excel导入导出工具类的简单实现及使用方法

    前言: 最近PM来了一个需求,简单来说就是在录入数据时一条一条插入到系统显得非常麻烦,让我实现一个直接通过excel导入的方法一次性录入所有数据.网上关于excel导入导出的例子很多,但大多相互借鉴. ...

  7. excel 导入导出使用poi自定义注解

    excel导入导出使用poi自定义注解 最近在做一个数据导入导出的模块 在网上找了一些例子 在这里整理一下 这里就不再贴原作者的地址  (以下代码来自网上非原创 稍作简单修改)  首先引入pom.xm ...

  8. java Excel导入导出工具类 及使用demo

    java Excel导入导出工具类 及使用demo 前言:相信进来的都是想尽快解决问题的,话不多说,按照以下步骤来,可以操作导出excel到本地,导入同理,自行学习.步骤一:直接复制以下excel工具 ...

  9. 优雅的实现 Excel 导入导出

    日常在做后台系统的时候会很频繁的遇到Excel导入导出的问题,正好这次在做一个后台系统,就想着写一个公用工具来进行Excel的导入导出. 一般我们在导出的时候都是导出的前端表格,而前端表格同时也会对应 ...

最新文章

  1. linux c 实现 http get post 请求
  2. fastjson将json字符串转为Map对象,拿走不谢
  3. Dell在CRM的创新及该模式的推广
  4. 大数据风控-反欺诈之黑卡与养卡
  5. Spring - Java/J2EE Application Framework 应用框架 第 15 章 EJB的存取和实现
  6. 【C#】【Thread】上下文同步域SynchronizationAttribute
  7. C++使用Json作为数据包装格式的通信
  8. Postgresql时间处理
  9. 择天记服务器维护中,择天记修仙正统
  10. 【AI】统计学和机器学习到底有什么区别?
  11. Python文件的读取与写入
  12. 用ikvm 来把java类库转换成_net类库,IKVM.NET
  13. 【PAT】1001 害死人不偿命的(3n+1)猜想
  14. visual studio community 2019 编译调试linux环境下程序
  15. 如何从一个USB上安装Windows Vista
  16. jsp 之 入门 jsp代码块
  17. 记一次hsql解析大json的全过程
  18. java Base64带秘钥的加密解密
  19. java抽象和接口的理解_Java学习笔记16---抽象类与接口的浅显理解
  20. mysql支付账单怎么设计_订单与支付设计

热门文章

  1. 哔哩哔哩2020校园招聘前端笔试卷(一)答案解析
  2. Django 实现搜索结果分页(筛选结果分页),以及优雅添加多个筛选条件
  3. 蓝桥杯省赛 走方格(多种方法)
  4. C++ sprintf 方法使用示例( for循环数组,字符串拼接、删除、格式化等)
  5. 如何在路演中获得投资机会|兆骑科创
  6. 白领沉迷EXCEL式生存
  7. 直播中常用的美颜sdk动态贴纸功能是什么?技术怎么实现的?
  8. ubuntu 16.04/18.04安装TP-LINK TL-WDN5200H无线USB网卡驱动
  9. 算命大师元真先生解读周易人生命运
  10. Java集合--阻塞队列(ArrayBlockingQueue)