EasyExcel实战与笔记

news/2024/11/14 22:26:28/

概述

Excel导入导出是业务开发中非常常见的需求。本文记录一下如何快速入门使用EasyExcel,深度实战,以及遇到的问题。

入门

使用EasyExcel导入如下依赖即可:

<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId>
</dependency>

使用EasyExcel主要是两类场景:

  1. 上传Excel文件并解析Sheet里数据,数据校验,脏数据清除,数据落库等;
  2. 从数据库里查询到数据后,下载导出为Excel;

一般而言,实现上面两个需求场景时,都会提供一个工具类

/*** excel 导出** @param fileName         fileName* @param fileNameTemplate 需要提供模板* @param data             list<PO>* @throws IOException 调用方处理*/
public static ResponseEntity<Resource> excelExport(String fileName, String fileNameTemplate, Object data) throws IOException {/** 填充文件 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替 {} 代表普通变量 {.} 代表是list的变量*/InputStream inputStream = getResourcesFileInputStream(fileNameTemplate);fileName = fileName + ".xlsx";ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(inputStream).build();WriteSheet writeSheet = EasyExcel.writerSheet().build();writeSheet.setSheetName(fileName);FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.VERTICAL).build();excelWriter.fill(data, fillConfig, writeSheet);// 关闭流excelWriter.finish();File dbfFile = new File(fileName);if (!dbfFile.exists()) {dbfFile.createNewFile();}HttpHeaders headers = new HttpHeaders();headers.add("Content-disposition", "attachment; filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));InputStreamResource resource = new InputStreamResource(new FileInputStream(dbfFile));return ResponseEntity.ok().headers(headers).contentLength(dbfFile.length()).contentType(MediaType.parseMediaType("application/octet-stream;charset=UTF-8")).body(resource);
}private static InputStream getResourcesFileInputStream(String fileName) {return Thread.currentThread().getContextClassLoader().getResourceAsStream("" + fileName);
}

上传

导出

Controller层接口使用上面的excelExport导出方法:

@ApiOperation(value = "数据统计服务-数据概览-性别", notes = "数据概览-性别")
@PostMapping("/overview/sex/excel")
public ResponseEntity<Resource> overviewSex(HttpServletResponse response, @RequestBody CommonQueryParam param) throws IOException {// 仅作为示例,一般不会在controller层写业务biz逻辑List<SexExcel> sexExcelList = getList(param);	return ExcelUtils.excelExport("性别数据", "sexTemplate.xlsx", sexExcelList);
}

然后提供一个sexTemplate.xlsx模板文件,放在classpath路径下面,一般都是src/main/resources路径下面:

在这里插入图片描述
对应于Excel模板文件的POJO实体类定义如下:

@Data
public class SexExcel {private String date;private String source;private String sex;private Long number;
}

需要注意的就是controller层接口请求参数里必须要有HttpServletResponse response,返回类型得是ResponseEntity<Resource>

基本上入门使用就是上面这些内容。

问题

记录几个在使用EasyExcel时遇到的问题。

NoClassDefFoundError: org/apache/poi/util/DefaultTempFileCreationStrategy

背景:之前已离职同事写的屎山代码,使用原生poi导出Excel,问题太多,包括但不限于接口超时,CPU飙高等。
在这里插入图片描述
还有个流关闭异常的报错:failed UT010029: Stream is closed,因为打印日志时使用e.getMessage(),没有打印出报错堆栈。

网络上关于原生POI的问题不要太多,包括office 2007和2010适配,占用内存高,占用CPU,代码冗长等。

于是,有了用EasyExcel替换原生POI的想法。导入EasyExcel,Debug模式启动应用失败,详细的报错信息如下:

Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: org/apache/poi/util/DefaultTempFileCreationStrategy
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: org/apache/poi/util/DefaultTempFileCreationStrategy
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1054)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)

很常见的报错,参考Java学习之NoClassDefFoundError、ClassNotFoundException、NoSuchMethodError。NoClassDefFoundError一般是多个版本的三方jar包并存时依赖冲突导致。

检查一下pom.xml文件,之前使用原生POI导出引入版本号:

<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.11</version>
</dependency>

改造引入的EasyExcel-2.2.11,依赖的版本为:
在这里插入图片描述
删除poi-3.11版本解决问题。

ExcelGenerateException: Calling the ‘fill’ method must use a template

报错日志为:

at com.alibaba.excel.write.ExcelBuilderImpl.fill(ExcelBuilderImpl.java:72)
at com.alibaba.excel.ExcelWriter.fill(ExcelWriter.java:185)
at com.aba.common.utils.ExcelUtils.excelExport(ExcelUtils.java:47)

定义好Excel模板,也定义好POJO实体类,但是在业务编码时,会发现另一个拼写更适合一些,比如把name换成alias,两边不一致时,就有这个问题。

@Data
public class DaTongUser {private Integer index;private String name;private String mobile;
}

对应的Excel模板文件:
在这里插入图片描述

NullPointerException: null

具体的报错信息:

at com.alibaba.excel.write.executor.ExcelWriteFillExecutor.doFill(ExcelWriteFillExecutor.java:191)
at com.alibaba.excel.write.executor.ExcelWriteFillExecutor.fill(ExcelWriteFillExecutor.java:118)
at com.alibaba.excel.write.ExcelBuilderImpl.fill(ExcelBuilderImpl.java:78)
at com.alibaba.excel.ExcelWriter.fill(ExcelWriter.java:185)
at com.aba.common.utils.ExcelUtils.excelExport(ExcelUtils.java:47)

参考


http://www.ppmy.cn/news/434068.html

相关文章

lazarus开发:快速读写excel文件的神奇控件——FPSpreadsheet

目录 1 简介 2 用wps制作一个简单的工资表 3 编译一下自带的演示程序 1 简介 FPSpreadsheet是一个功能强大的控件库&#xff0c;用于读取和写入电子表格文件。使用该控件库开发的软件&#xff0c;能够在不安装电子表格应用程序的情况下&#xff0c;快速读出、写入电子表格文…

内存泄漏问题排查_malloc重载

linux疑难问题排查实战专栏,分享了作为公司专家,在解决内存、性能、各类死机等疑难问题的排查经验,认真学习可以让你在日后工作中大放光彩。 C/C++开发的程序执行效率很高,但却经常受到内存泄漏的困扰。本文提供一种通过wrap malloc查找memory leak的思路,有静态链…

编程珠玑课后习题答案 第三章

第三章 数据决定程序结构 1. 本书行将出版之时&#xff0c;美国的个人所得税分为 5 种不同的税率&#xff0c;其中最大的税率大约为 40%。以前的情况则更为复杂&#xff0c;税率也更高。下面所示的程序文本采用 25 个 if 语句的合理方法来计算 1978 年的美国联邦所得税。税率序…

给文件夹设置密码

右键文件&#xff0c;在压缩文件的选项中有&#xff0c;也就是最后解压缩文件需要密码

win10系统服务器怎样设置密码,win10系统的电脑如何给普通文件夹设置密码

很多用户对于win10系统中的一些功能设置都还不太了解&#xff0c;就比如我们平时在使用电脑时&#xff0c;一些特殊的重要机密文件是需要加密的&#xff0c;这样才能保证不会被别人查看或者修改&#xff0c;很多用户都还不知道在win10系统的电脑中要如何对文件夹进行加密&#…

如何使用计算机对文件修改密码,文件夹怎么设置密码?怎么给文件夹设置密码?...

随着互联网的发展&#xff0c;各种信息传播都很快捷&#xff0c;个人隐私的文件不小心就会丢失&#xff0c;所以很多人想到了如何给文件夹加密码来解决这一问题。那么文件夹怎么设置密码?怎么给文件夹设置密码&#xff1f;下面就为大家详细介绍一下&#xff0c;来看看吧&#…

Golang将文件夹压缩为ZIP格式并加密

啥都不说了&#xff0c;直接上代码。 import ("archive/zip""io""os""path/filepath""strings"ezip "github.com/alexmullins/zip" )// CompressPathToZip 压缩文件夹 func CompressPathToZip(path, targetFile …

计算机里的文档怎么设置密码,文件夹怎么设置密码,教您如何给电脑上文件夹设置密码...

电脑在现在是越来越普及&#xff0c;有时候出于隐私的原因&#xff0c;自己的电脑上一些文件并不想让他人看到&#xff0c;但是有时自己会有离开电脑的时候&#xff0c;又或者是别人想借用一下自己的电脑&#xff0c;怎么办&#xff1f;为了防止别人发现&#xff0c;我们可以给…