EasyExcel 快速入门
目录
一、 EasyExcel简介
官网链接:
代码链接:
二、 EasyExcel快速上手
引入依赖:
设置Excel相关注解
编写对应的监听类:
简单写入数据:
简单读取数据:
不需要使用监听器:
需要使用监听器:
三、EasyExcel进阶操作
批量写入数据:
批量写入不同的sheet的不同对象:
填充数据:
四、实战EasyExcel(Excel表格的导入和导出)
一、 EasyExcel简介
EasyExcel 是一个基于 Java 的简单、高效的 Excel 处理工具。它由阿里巴巴开源,主要解决了在 Java 应用中处理 Excel 文件时内存溢出的问题。
EasyExcel 和 Apache POI 都是 Java 生态中处理 Excel 文件的库,但它们在设计理念、性能、使用复杂度等方面有所不同。以下是 EasyExcel 相比于 Apache POI 的主要优势和一些差异:
性能:
-
内存占用:EasyExcel 是为低内存占用而设计的。在处理大型 Excel 文件时,EasyExcel 可以实现按行读取和写入,而不需要将整个文件加载到内存中,从而显著降低内存使用。而 Apache POI 在处理大型文件时,可能会因为将整个文件加载到内存而导致内存溢出。
-
处理速度:EasyExcel 对读取和写入操作进行了优化,通常在处理速度上比 Apache POI 更快。
使用复杂度:
-
API 设计:EasyExcel 提供了更为简洁的 API,使得读取和写入操作更加直观和方便。而 Apache POI 提供了丰富的 API,但这也使得它的使用相对复杂。
-
模型映射:EasyExcel 支持使用注解直接将 Excel 的列映射到 Java 实体的字段上,简化了数据转换的过程。Apache POI 需要手动处理每一行和每一列的数据。
官网链接:
EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel 官网 (alibaba.com)
代码链接:
https://gitee.com/seniorGitee/easy-excel
二、 EasyExcel快速上手
引入依赖:
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>4.0.2</version>
</dependency>
设置Excel相关注解
以员工实体类为例:
@ExcelIgnore设置忽略导出的字段信息
@ExcelProperty设置导出的字段名,导出的字段默认按照顺序从0开始排序,如果想指定导出字段的在第几列的话,可以设置对应的index,index的值:字段所在列数-1,类似数组下标索引
@DateTimeFormat定义日期格式
@ColumnWidth设置字段宽度
其实@ExcelProperty还有很多复杂的操作,具体请查看官网文档,这里只教会大家快速入门使用
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee implements Serializable {/*** 忽略这个字段*/@ExcelIgnoreprivate Long id;@ExcelProperty("员工名")private String name;@ExcelProperty("员工年龄")private Integer age;@ExcelProperty(value = "员工工资",index = 3)private BigDecimal salary;@ColumnWidth(15)@DateTimeFormat("yyyy年MM月dd日")@ExcelProperty(value = "入职时间",index = 2)private Date entryTime;}
编写对应的监听类:
编写Employee对应的监听类EmployeeListener
注意:有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Slf4j
public class EmployeeListener implements ReadListener<Employee> {/*** 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 100;/*** 缓存的数据*/private List<Employee> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);private IEmployeeService employeeService;public EmployeeListener(IEmployeeService employeeService){this.employeeService = employeeService;}//每一条数据解析都会进行调用@Overridepublic void invoke(Employee employee, AnalysisContext analysisContext) {log.info("解析到一条数据:{}", JSON.toJSONString(employee));cachedDataList.add(employee);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (cachedDataList.size() >= BATCH_COUNT) {saveData();// 存储完成清理 listcachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);}}//所有的数据解析完后进行调用@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {// 这里也要保存数据,确保最后遗留的数据也存储到数据库saveData();log.info("所有数据解析完成!");}/*** 加上存储数据库*/private void saveData() {log.info("{}条数据,开始存储数据库!", cachedDataList.size());employeeService.save(cachedDataList);log.info("存储数据库成功!");}
}
简单写入数据:
注意:simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大参照 重复多次写入(可以查看EasyExcel进阶操作:批量写入数据)
@SpringBootTest
class EasyExcelApplicationTests {@Autowiredprivate IEmployeeService employeeService;@Testvoid simpleWrite() {String fileName = ".\\src\\main\\resources\\static\\"+"simpleWrite" + System.currentTimeMillis() + ".xlsx";EasyExcel.write(fileName, Employee.class).sheet("模板").doWrite(employeeService.getData());}}
在resources/static中可以看到导出数据的Excel表格

简单读取数据:
读取数据有两种方式,分别是使用监听器和不使用监听器的方式进行读取数据
不需要使用监听器:
这里的fileName需要修改成读取Excel文件对应的路径
@SpringBootTest
@Slf4j
class EasyExcelApplicationTests {@Autowiredprivate IEmployeeService employeeService;@Testvoid simpleRead(){String fileName = ".\\src\\main\\resources\\static\\"+"simpleWrite1726145097517.xlsx";// 这里默认每次会读取100条数据 然后返回过来 直接调用使用数据就行// 具体需要返回多少行可以在`PageReadListener`的构造函数设置EasyExcel.read(fileName, Employee.class, new PageReadListener<Employee>(employeeList -> {for (Employee employee : employeeList) {log.info("读取到一条数据{}", JSON.toJSONString(employee));}})).sheet().doRead();}}
控制台输出的结果:

需要使用监听器:
这里的EmployListener对一个之前写的监听类,读取Excel文件的数据并将数据存储到数据库中
@SpringBootTest
@Slf4j
class EasyExcelApplicationTests {@Autowiredprivate IEmployeeService employeeService;@Testvoid simpleReadByListener(){String fileName = ".\\src\\main\\resources\\static\\"+"simpleWrite1726145097517.xlsx";// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭EasyExcel.read(fileName, Employee.class, new EmployeeListener(employeeService)).sheet().doRead();}}
控制台输出的结果:

三、EasyExcel进阶操作
批量写入数据:
批量写入通一个sheet同一对象:
@SpringBootTest
@Slf4j
class EasyExcelApplicationTests {@Autowiredprivate IEmployeeService employeeService;@Testvoid batchWriteOneSheep(){// 方法1: 如果写到同一个sheetString fileName = ".\\src\\main\\resources\\static\\"+"simpleWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写try (ExcelWriter excelWriter = EasyExcel.write(fileName, Employee.class).build()) {// 这里注意 如果同一个sheet只要创建一次WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();Long total = employeeService.total();Integer pageSize = 10;// 实际使用时根据数据库分页的总的页数来,这里批量插入,每次插入10条数据for (int i = 1; i <= Math.ceil((double) total /pageSize); i++) {// 分页去数据库查询数据 这里可以去数据库查询每一页的数据PageBean pageBean = employeeService.pageEmployee(i,pageSize);excelWriter.write(pageBean.getRows(), writeSheet);}}}}
批量写入不同的sheet同一对象:
@SpringBootTest
@Slf4j
class EasyExcelApplicationTests {@Autowiredprivate IEmployeeService employeeService;@Testvoid batchWriteDifferentSheep(){// 方法2: 如果写到不同的sheet 同一个对象String fileName = ".\\src\\main\\resources\\static\\"+"simpleWrite" + System.currentTimeMillis() + ".xlsx";// 这里 指定文件try (ExcelWriter excelWriter = EasyExcel.write(fileName, Employee.class).build()) {Long total = employeeService.total();Integer pageSize = 10;// 实际使用时根据数据库分页的总的页数来。这里最终会将数据写到多个sheet里面for (int i = 1; i <= Math.ceil((double) total /pageSize); i++) {// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样WriteSheet writeSheet = EasyExcel.writerSheet(i, "员工表" + i).build();// 分页去数据库查询数据 这里可以去数据库查询每一页的数据PageBean pageBean = employeeService.pageEmployee(i,pageSize);excelWriter.write(pageBean.getRows(), writeSheet);}}}}
批量写入不同的sheet的不同对象:
@SpringBootTest
@Slf4j
class EasyExcelApplicationTests {@Autowiredprivate IEmployeeService employeeService;@Testvoid batchWriteDifferentSheepAndObject(){// 方法3 如果写到不同的sheet 不同的对象String fileName = ".\\src\\main\\resources\\static\\"+"simpleWrite" + System.currentTimeMillis() + ".xlsx";// 这里 指定文件try (ExcelWriter excelWriter = EasyExcel.write(fileName).build()) {Long total = employeeService.total();Integer pageSize = 10;// 实际使用时根据数据库分页的总的页数来。这里最终会将数据写到多个sheet里面for (int i = 1; i <= Math.ceil((double) total /pageSize); i++) {// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。这里注意Employee.class 可以每次都变,我这里为了方便 所以用的同一个class// 实际上可以一直变WriteSheet writeSheet = EasyExcel.writerSheet(i, "模版表" + i).head(Employee.class).build();// 分页去数据库查询数据 这里可以去数据库查询每一页的数据PageBean pageBean = employeeService.pageEmployee(i,pageSize);excelWriter.write(pageBean.getRows(), writeSheet);}}}}
填充数据:
例如我们想将员工表填充到如下的Excel表格中

先对Excel表格模版填写占位符

执行填充Excel表格的代码
@SpringBootTest
@Slf4j
class EasyExcelApplicationTests {@Autowiredprivate IEmployeeService employeeService;@Testvoid fillTemplateData(){//需要填充模版String templateFileName = ".\\src\\main\\resources\\static\\"+"fillTemplate.xlsx";//模版填充后的文件String fileName = ".\\src\\main\\resources\\static\\"+"fillTemplateComplete.xlsx";// 这里 会填充到第一个sheet, 然后文件流会自动关闭EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(employeeService.getData());}}
四、实战EasyExcel(Excel表格的导入和导出)
web中进行Excel表格数据的导入和导出,以员工表为例:
@RestController
@RequestMapping("/employee")
public class EmployeeController {@Autowiredprivate IEmployeeService employeeService;@PostMapping("/upload")public void upload(MultipartFile file,HttpServletResponse response) throws IOException{long begin = System.currentTimeMillis();EasyExcel.read(file.getInputStream(), Employee.class, new EmployeeListener(employeeService)).sheet().doRead();long end = System.currentTimeMillis();response.setContentType("text/html;charset=utf-8");response.getWriter().println("导出数据成功,耗时:"+(end-begin));}@GetMapping("download")public void download(HttpServletResponse response) throws IOException {// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postmanresponse.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("导出的Excel数据", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");EasyExcel.write(response.getOutputStream(), Employee.class).sheet("员工表").doWrite(employeeService.getData());}}
相关文章:
EasyExcel 快速入门
目录 一、 EasyExcel简介 官网链接: 代码链接: 二、 EasyExcel快速上手 引入依赖: 设置Excel相关注解 编写对应的监听类: 简单写入数据: 简单读取数据: 不需要使用监听器: 需要使…...
Sparse4D v1
Sparse4D: Multi-view 3D Object Detection with Sparse Spatial-Temporal Fusion Abstract 基于鸟瞰图 (BEV) 的方法最近在多视图 3D 检测任务方面取得了重大进展。与基于 BEV 的方法相比,基于稀疏的方法在性能上落后,但仍然有很多不可忽略的优点。为了…...
速盾:你知道高防 IP 和高防 CDN 的区别吗?
在当今网络安全形势日益严峻的情况下,网站的安全防护成为了企业和个人关注的焦点。高防 IP 和高防 CDN 作为两种常见的网络安全防护手段,被广泛应用于网站的安全防护中。那么,高防 IP 和高防 CDN 有什么区别呢?防护网站哪个更好呢…...
HTML和CSS网页制作成品
HTML和CSS网页制作成品 一、引言 1. 背景介绍 在当今数字化时代,网页已成为信息传递和交流的重要媒介。HTML和CSS作为网页制作的基石,对于构建美观、功能丰富的网站至关重要。本文将详细介绍如何使用HTML和CSS来制作一个网页成品。 2. 目的和重要性 …...
Ai+若依(集成easyexcel实现excel表格增强)
EasyExcel 介绍 官方地址:EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel 官网 Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一…...
钻机、塔吊等大型工程设备,如何远程维护、实时采集运行数据?
在建筑和工程领域,重型设备的应用不可或缺,无论是在道路与桥梁建设、高层建筑施工,还是在风电、石油等能源项目的开发中,都会用到塔吊、钻机等大型机械工程设备。 随着数字化升级、工业4.0成为行业发展趋势,为了进一步…...
【AutoX.js】选择器 UiSelector - 查找包名
文章目录 原文:https://blog.c12th.cn/archives/38.html选择器 UiSelector - 查找包名笔记直接查找包名双层判断(推荐)查找最外层控件的子控件 最后 原文:https://blog.c12th.cn/archives/38.html 选择器 UiSelector - 查找包名 笔记 AutoX.js UiSelec…...
ERP进销存多仓库管理系统源码 带完整的安装代码包以及搭建部署教程
系统概述 ERP进销存多仓库管理系统是一款专为中小企业量身定制的集成化管理软件,它集成了采购管理、销售管理、库存管理、财务管理以及多仓库协同作业等核心模块。通过统一的平台,企业可以实时掌握商品从入库到出库的全过程,实现库存的自动化…...
数据清洗-缺失值填充-对XGBoost参数优化填充
目录 一、安装所需的python包二、采用XGboost算法进行缺失值填充2.1可直接运行代码2.2以某个缺失值数据进行实战2.2.1 代码运行过程截屏:2.2.2 填充后的数据截屏:三、网格搜索(Grid Search)对 XGBoost 模型的超参数进行优化原理介绍3.1 说明3.2 参数优化的原理1. 网格搜索(…...
Qt_按钮类控件
目录 1、QAbstractButton 2、设置带图标的按钮 3、设置带有快捷键的按钮 4、QRadioButtion(单选按钮) 4.1 QButtonGroup 5、QCheckBox 结语 前言: 按钮类控件是Qt中最重要的控件类型之一,该类型的控件可以通过鼠标的点击…...
union 的定义和基本结构以及用途
在 C 语言中,union(联合体) 是一种数据结构,它允许多个成员共享相同的内存空间。换句话说,联合体中的所有成员都存储在同一块内存区域,不同的成员会占用相同的内存地址,但在同一时刻只能保存一个…...
混合整数规划及其MATLAB实现
目录 引言 混合整数规划的基本模型 混合整数规划的求解方法 MATLAB中的混合整数规划实现 示例:多变量系统的混合整数规划 表格总结:混合整数规划的求解方法与适用场景 结论 引言 混合整数规划(Mixed Integer Programming, MIP…...
【数据结构】6——图1,概念
数据结构6——图1,概念 文章目录 数据结构6——图1,概念基本概念图的分类图的表示方法 基本概念 由 顶点(Vertex) 和 边(Edge) 组成的集合。顶点表示图中的点,而边表示顶点之间的连接。记为 G …...
技术周总结 09.09~09.15周日(C# WinForm WPF)
文章目录 一、09.09 周一1.1) 问题01: Windows桌面开发中,WPF和WinForm的区别和联系?联系:区别: 二、09.12 周四2.1)问题01:visual studio的相关快捷键有哪些?通用快捷键编辑导航调试窗口管理 2…...
4K投影仪选购全攻略:全玻璃镜头的当贝F6,画面细节纤毫毕现
在当今的投影市场上,4K投影仪已经成了主流产品,越来越多家庭开始关注如何选择一款性价比高、口碑好的4K投影仪。4K投影仪其实指的是具备3840*2160像素分辨率投影仪,它能够提供更清晰、更细腻、更真实的画面效果。 那么4K投影仪该怎么选&…...
除了字符串前导的*号之外,将串中其它*号全部删除
要求 假定输入的字符串中只包含字母和*号。请编写函数fun,它的功能是:除了字符串前导的*号之外,将串中其它*号全部删除。在编写函数时,不得使用C语言提供的字符串函数。函数fun中给出的语句仅供参考。 例如,字符串中的内容为:-**…...
SpringBoot开发——使用@Slf4j注解实现日志输出
文章目录 1、Lombok简介2、SLF4J简介3、实现步骤3.1 创建SpringBoot项目3.2 添加依赖3.3 使用 Slf4j 注解3.4 输出日志信息 4、结论 在现代Java开发中,日志记录是至关重要的。它不仅帮助开发者调试代码,还便于监控系统运行状态和性能。 Lombok 和 SLF4J …...
VSCode拉取远程项目
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...
【已解决】SpringBoot3项目整合Druid依赖:Druid监控页面404报错
文章标题 问题描述原因分析解决方案参考资料 问题描述 最近,笔者在SpringBoot3项目中整合Druid连接池时,偶然翻到一条介绍Druid监控的短视频,兴致盎然之下尝试设置了一下Druid监控。 But,按照视频中提供的yml参数对照设置&#x…...
【算法】滑动窗口—找所有字母异位词
“找到字符串中所有字母异位词”的难度为Medium,看一下题目: 给定一个字符串 S 和一个非空字符串 T,找到 S 中所有是 T 的字母异位词的子串,返回这些子串的起始索引。 所谓的字母异位词,其实就是全排列,原题…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
