EasyExcel实战与笔记

news/2024/7/21 7:09:23 标签: excel

概述

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.niftyadmin.cn/n/442317.html

相关文章

msvcp110.dll丢失原因——msvcp110.dll丢失怎么修复(最新可修复)

昨天卸载了一个垃圾软件以后&#xff0c;我的其他软件就无法打开运行&#xff0c;提示msvcp110.dll丢失&#xff0c;无法继续执行此代码。今天早上找了很多方法&#xff0c;终于把msvcp110.dll丢失的原因以及修复的方法都弄明白了。msvcp110.dll是一个非常重要的文件&#xff0…

【干货】Android系统定制基础篇:第一部分

1、Android指定某个文件的权限 当需要修改某文件或路径权限时&#xff0c;我们可以在init.rc开机启动某节点添加chmod命令进行修改。但是对于system分区&#xff0c;由于是ro权限&#xff0c;在init.rc使用chmod修改权限无效。需要在文件编译时&#xff0c;对权限进行修改。不…

磁盘调度算法及其应用

导读&#xff1a; 磁盘调度是计算机系统中的重要问题之一。在多个进程同时访问磁盘时&#xff0c;合理的磁盘调度算法可以优化磁盘访问顺序&#xff0c;提高系统性能。本文将介绍磁盘调度算法的基本思想&#xff0c;并通过一个实验来模拟不同调度算法的运行过程。 正文&#…

英语六级作文

英语六级作文 议论文&#xff08;一&#xff09;开头&#xff08;二&#xff09;主体&#xff08;三&#xff09;结尾 图表文 议论文 &#xff08;一&#xff09;开头 第一句 With regard to…, viewpoints vary considerably. 第二句 As far as I am concerned, I am in lin…

【Vue3学习】Vuex 状态管理 store

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 库。它采用集中式存储管理应用的所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。 安装 npm npm install vuexnext --saveyarn npm install vuexnext --save基本使用 1&#xff09;创建…

记录好项目D7

记录好项目 你好呀&#xff0c;这里是我专门记录一下从某些地方收集起来的项目&#xff0c;对项目修改&#xff0c;进行添砖加瓦&#xff0c;变成自己的闪亮项目。修修补补也可以成为毕设哦 本次的项目是个酒店预订管理系统 技术栈&#xff1a;springbootjavamysqlmybatis …

Gitlab CI/CD入门(一)Python项目的CI演示

本文将介绍CI/CD的基本概念&#xff0c;以及如何使用Gitlab来实现CI/CD。   本文介绍的CI/CD项目为个人Gitlab项目&#xff1a;gitlab_ci_test&#xff0c;访问网址为&#xff1a;https://gitlab.com/jclian91/gitlab_ci_test。 CI/CD的含义 在现代软件工程中&#xff0c;CI…

SpringSecurity从入门到精通

简介 ​ Spring Security 是 Spring 家族中的一个安全管理框架。相比与另外一个安全框架Shiro&#xff0c;它提供了更丰富的功能&#xff0c;社区资源也比Shiro丰富。 ​ 一般来说中大型的项目都是使用SpringSecurity 来做安全框架。小项目有Shiro的比较多&#xff0c;因为相比…