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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/427283.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

视频工具EasyDarwin将本地视频生成RTSP给WVP拉流列表

效果 ffmpeg生成rtsp流 EasyDarwin的rtsp端口默认的是10054, 使用ffmpeg将本地视频转到EasyDarwin的rtsp。 F:\rtsp\ffmpeg-7.0.2-essentials_build\bin>ffmpeg -re -i F:\rtsp\123.mp4 -rtsp_transport tcp -vcodec h264 -f rtsp rtsp://127.0.0.1:10054/video11 它的直播…

Yocto - 使用Yocto开发嵌入式Linux系统_01 前言

Embedded Linux Development Using Yocto Project: Leverage the power of the Yocto Project to build efficient Linux-based products, Third Edition By: Otavio Salvador, Daiane Angolini Overview of this book Yocto 项目是开发可靠的嵌入式 Linux 项目的行业标准。与…

【网络安全】-文件包含漏洞-pikachu

文件操作漏洞包括文件上传漏洞&#xff0c;文件包含漏洞&#xff0c;文件下载漏洞。 文章目录 前言 : 什么是文件包含漏洞&#xff1f; 1.文件包含漏洞的分类&#xff1a; 本地文件包含漏洞&#xff1a; 远程文件包含漏洞&#xff1a; 2.两种文件包含漏洞的区别&#xff1a; 3.…

【资料分析】刷题日记2

第一套 √ 2013-2016一共有13&#xff0c;14&#xff0c;15&#xff0c;16四年&#xff0c;亦即16 - 13 1 4年 √ 是多少倍 ③vs④&#xff1a;都是只给出了年均增速&#xff0c;③求的是其中一年的&#xff0c;无法确定&#xff1b;④求的是这个时段总共的&#xff0c;可…

Leetcode 93-复原 IP 地址

有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 ‘.’ 分隔。 例如&#xff1a;“0.1.2.201” 和 “192.168.1.1” 是 有效 IP 地址&#xff0c;但是 “0.011.255.245”、“192.168.…

O1-preview:智能预测与预取驱动的性能优化处理器设计OPEN AI

# 创作不易&#xff0c;您的打赏、关注、点赞、收藏和转发是我坚持下去的动力&#xff01; O1-preview 是一种用于性能优化的处理器设计原理&#xff0c;主要通过智能预测和数据预取来提升处理器的执行效率。以下是对 O1-preview 原理的详细介绍&#xff0c;以及它相对于以往的…

腾讯音乐 2024乐圃音乐空间夏令营:以音乐传递爱,点亮公益之光

8 月 25 日晚&#xff0c;在四川北川&#xff0c;一场充满无尽 “乐” 趣的结营音乐会&#xff0c;为 2024 年乐圃音乐空间夏令营画上了完美的句号。这个由腾讯音乐娱乐集团&#xff08;Tencent Music Entertainment Group&#xff0c;以下简称 “TME”&#xff09;旗下腾讯音乐…

上架谷歌安卓APP完整图文流程

本节包含以下内容&#xff1a; 第一步&#xff1a;登录Google play开发者后台第二步&#xff1a;创建应用第三步&#xff1a;设置应用第四步&#xff1a;开启通知第五步&#xff1a;发布应用第六步&#xff1a;查看审核结果第七步&#xff1a;配置app支付参数第八步&#xff1…

论文速递!时序预测!DCSDNet:双卷积季节性分解网络,应用于天然气消费预测过程

本期推文将介绍一种新的时序预测方法:双卷积季节性分解网络&#xff08;Dual Convolution withSeasonal Decomposition Network, DCSDNet&#xff09;在天然气消费预测的应用&#xff0c;这项研究发表于《Applied Energy》期刊。 针对天然气消费的多重季节性和非规律性&#x…

C++ —— 关于vector

目录 链接 1. vector的定义 2. vector的构造 3. vector 的遍历 4. vector 的扩容机制 5. vector 的空间接口 5.1 resize 接口 5.2 push_back 5.3 insert 5.4 erase 5.5 流插入与流提取 vector 并不支持流插入与流提取&#xff0c;但是可以自己设计&#xff0c;更…

二进制补码及与原码的互相转换方法-成都仪器定制

大沙把一些基础的知识说清楚&#xff0c;本文介绍二进制补码及与原码的转换方法。 先说原码&#xff0c;原码‌是一种计算机中对数字的二进制定点表示方法。在原码表示法中&#xff0c;数值前面增加了一位符号位&#xff0c;最高位为符号位&#xff0c;0表示正数&#xff0c;1表…

SPI接口通信协议浅谈成都自动化开发

沙鸥-成都 1 什么是SPI SPI是串口外设接口的缩写&#xff0c;是一种高速的、全双工、同步的通信协议&#xff0c;是微处理器与外围IC之间常用的一种通讯方式。 SPI是主从式的通信协议&#xff0c;可以一主机一从机通信&#xff0c;也可以一主机多从机通信。 2 SPI的优缺点 SPI接…

模版进阶(template)

1.非类型模版参数 模版参数分类类型形参与非类型形参。 ① 类型形参&#xff1a;出现在在模板参数列表中&#xff0c;跟在class或者typename之类的参数类型名称。 ② 非类型形参&#xff0c;就是用一个常量作为类(函数)模板的一个参数&#xff0c;在类(函数)模板中可将该参数当…

Leetcode Hot 100刷题记录 -Day14(矩阵置0)

矩阵置0 问题描述&#xff1a; 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]]示例 2&#xff1a;…

sqli-labs靶场搭建

下载了一个phpstudy进行搭靶场搭建 然后打开phpstudy安装好php,mysql等环境 正式sqli-labs靶场搭建 第一步&#xff1a;下载源码&#xff1a;https://codeload.github.com/Audi-1/sqli-labs/zip/master 解压后放进网站根目录&#xff0c;进到 sqli-labs的文件夹下&#xff0…

[2025]医院健康陪诊系统(源码+定制+服务)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

二叉树的链式结构和递归程序的递归流程图

二叉树的链式存储结构是指&#xff0c;用链表来表示一棵二叉树&#xff0c;即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成&#xff0c;数据域和左右指针域&#xff0c;左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分…

基于Linux系统离线安装oracle数据库

注意事项&#xff1a; 在安装的时候多次涉及root用户和oracle用户的切换&#xff0c;请注意区分&#xff0c;本文已明显 一、环境准备 1、关闭防火墙 [rootlocalhost ~]# systemctl stop firewalld2、 禁用NetworkManager服务&#xff08;非必须&#xff09; [rootlocalhost …

STM32—I2C通信外设

1.I2C外设简介 STM32内部集成了硬件I2C收发电路&#xff0c;可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能&#xff0c;减轻CPU的负担支持多主机模型&#xff08;可变多主机&#xff09;支持7位/10位地址模式&#xff08;11110......)支持不同的通…

C++:布尔类型,引用,堆区空间

1.布尔类型 #include <iostream>using namespace std;int main() {bool b13;bool b20;cout << "b1" <<b1<< endl;cout << "b2" <<b2<< endl;cout <<boolalpha<< "b1" <<b1<<…