EasyExcel-最简单的读写excel工具类

前言:
easyExcel 的官网文档给的示例非常全,可以参考https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read
在此我贴出自己的工具类,可以直接用

导包

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

读excel

1:最简单读-使用demo对象

创建对象bean

package com.wkl.testdemo.excel;import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;/*** @author wangkanglu* @version 1.0* @description* @date 2023-12-08 17:28*/
@Data
public class DemoBean {/*** 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据*/@ExcelProperty("姓名")private String name;/*** 强制读取第二个 这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配*/@ExcelProperty(index = 1)private String sex;
}

创建读取器

package com.wkl.testdemo.excel;import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.util.ListUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;import java.util.List;/*** @author wangkanglu* @version 1.0* @description* @date 2023-12-08 17:27*/
@Data
public class DemoListener extends AnalysisEventListener<DemoBean> {/*** 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 100;/*** 缓存的数据*/private List<DemoBean> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);/*** 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。*/private DemoBean demoDAO;public DemoListener() {// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数demoDAO = new DemoBean();}@Overridepublic void onException(Exception exception, AnalysisContext context) throws Exception {if (exception instanceof ExcelDataConvertException) {Integer columnIndex = ((ExcelDataConvertException) exception).getColumnIndex() + 1;Integer rowIndex = ((ExcelDataConvertException) exception).getRowIndex() + 1;String message = "第" + rowIndex + "行,第" + columnIndex + "列,数据格式有误,请核实";System.out.println("导入数据转换出现错误: " + message);} else if (exception instanceof RuntimeException) {System.out.println("导入错误:" + exception);if (exception.getMessage().contains("列与模板上顺序不符,请勿修改表头模板")) {throw new RuntimeException(exception.getMessage());}}}@Overridepublic void invoke(DemoBean data, AnalysisContext analysisContext) {System.out.println("解析到一条数据:{}"+data);cachedDataList.add(data);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (cachedDataList.size() >= BATCH_COUNT) {saveData();// 存储完成清理 listcachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {// 这里也要保存数据,确保最后遗留的数据也存储到数据库saveData();System.out.println("解析完了");}/*** 加上存储数据库*/private void saveData() {System.out.println("{}条数据,开始存储数据库!"+ cachedDataList.size());
//        demoDAO.save(cachedDataList);System.out.println("存储数据库成功!");}}

测试程序

package com.wkl.testdemo.excel;import com.alibaba.excel.EasyExcel;import java.util.List;/*** @author wangkanglu* @version 1.0* @description* @date 2023-12-08 17:45*/
public class SimpleTest {public static void main(String[] args) {String path = "C:\\Users\\Desktop\\demo.xlsx";DemoListener listener = new DemoListener();EasyExcel.read(path,DemoBean.class,listener).sheet().doRead();List<DemoBean> cachedDataList = listener.getCachedDataList();System.out.println("end----");}
}

2:读取多个sheet

 public static void main(String[] args) {String path = "C:\\Users\\wenge\\Desktop\\demo.xlsx";DemoListener listener = new DemoListener();//生成读取对象ExcelReader excelReader = EasyExcel.read(path).build();//生成一个sheetReadSheet build = EasyExcel.readSheet(0).head(DemoBean.class).registerReadListener(listener).build();//读取多个sheetExcelReader read = excelReader.read(Arrays.asList(build));List<DemoBean> cachedDataList = listener.getCachedDataList();System.out.println("end----");

3:复杂头的读取

如果遇到这样的excel
在这里插入图片描述

创建对象bean

package com.wkl.testdemo.excel;import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;/*** @author wangkanglu* @version 1.0* @description* @date 2023-12-08 17:28*/
@Data
public class DemoBeanheads {/*** 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据*/@ExcelProperty({"大学","姓名"})private String name;/*** 强制读取第二个 这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配*/@ExcelProperty({"大学","性别"})private String sex;
}

读取器不变

测试程序

public static void main(String[] args) {String path = "C:\\Users\\Desktop\\demo.xlsx";DemoHeadListener listener = new DemoHeadListener();//生成读取对象ExcelReader excelReader = EasyExcel.read(path).build();//生成一个sheetReadSheet build = EasyExcel.readSheet(0).head(DemoBeanheads.class).registerReadListener(listener).headRowNumber(2).build();//读取多个sheetExcelReader read = excelReader.read(Arrays.asList(build));List<DemoBeanheads> cachedDataList = listener.getCachedDataList();System.out.println("end----");}

4:不创建对象的对

读取器

package com.wkl.testdemo.excel;import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;@Slf4j
public class NoHeadMapListener extends AnalysisEventListener<Map<Integer, String>> {private List<Map<Integer, String>> list = new ArrayList<>();private static final SimpleDateFormat sdfFormat = new SimpleDateFormat("yyyy-MM-dd");//表头private List<String> headList = Arrays.asList("姓名","性别");@Overridepublic void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {if (headMap==null){throw new RuntimeException("文件表头为空,请勿上传非法excel文件,请先下载对应的导入模板文件" );}if (headMap.size()!=headList.size()){throw new RuntimeException("文件表头列与模板不符,请勿上传非法excel文件,请先下载对应的导入模板文件" );}for (int i = 0; i < headList.size(); i++) {String tableHead = headMap.get(i);String head = headList.get(i);if (!head.equals(tableHead)) {throw new RuntimeException("表头中'" + tableHead + "'列与模板上顺序不符,请勿修改模板表头");}}}@Overridepublic void invoke(Map<Integer, String> integerStringMap, AnalysisContext analysisContext) {
//        log.info("解析到一条数据:{}", JSON.toJSONString(integerStringMap));List<String> picList = new ArrayList<>();if (!ObjectUtils.isEmpty(integerStringMap)) {list.add(integerStringMap);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {log.info("所有数据解析完成!");}@Overridepublic void onException(Exception exception, AnalysisContext context) throws Exception {if (exception instanceof ExcelDataConvertException) {Integer columnIndex = ((ExcelDataConvertException) exception).getColumnIndex() + 1;Integer rowIndex = ((ExcelDataConvertException) exception).getRowIndex() + 1;String message = "第" + rowIndex + "行,第" + columnIndex + "列,数据格式有误,请核实";log.error("导入数据转换出现错误: " + message);} else if (exception instanceof RuntimeException) {log.error("导入错误:" + exception);if (exception.getMessage().contains("列与模板上顺序不符,请勿修改表头模板")) {throw new RuntimeException(exception.getMessage());}}}public List<String> getHeadList() {return headList;}public void setHeadList(List<String> headList) {this.headList = headList;}public List<Map<Integer, String>> getList() {return list;}}

测试程序

 public static void main(String[] args) {String path = "C:\\Users\\Desktop\\demo.xlsx";NoHeadMapListener listener = new NoHeadMapListener();EasyExcel.read(path, listener).sheet().doRead();List<String> headList = listener.getHeadList();List<Map<Integer, String>> list = listener.getList();System.out.println("end");}

读取后的得到的数据列表:
在这里插入图片描述

写excel

1:最简单的写

创建对象

@Getter
@Setter
@EqualsAndHashCode
public class DemoData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;/*** 忽略这个字段*/@ExcelIgnoreprivate String ignore;
}

测试程序

List<DemoData> data = new ArrayList();
fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭// 如果这里想使用03 则 传入excelType参数即可EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data);

测试程序-导出指定列

List<DemoData> data = new ArrayList();
fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";// 根据用户传入字段 假设我们要忽略 name列Set<String> excludeColumnFiledNames = new HashSet<String>();excludeColumnFiledNames.add("name");// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, DemoData.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板").doWrite(data);// 根据用户传入字段 假设我们只要导出 name列Set<String> includeColumnFiledNames = new HashSet<String>();includeColumnFiledNames.add("name");// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, DemoData.class).includeColumnFiledNames(includeColumnFiledNames).sheet("模板").doWrite(data);

2:数据写到不同的sheet

fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";// 这里 指定文件try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面for (int i = 0; i < 5; i++) {// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();// 分页去数据库查询数据 这里可以去数据库查询每一页的数据List<DemoData> data = data();excelWriter.write(data, writeSheet);}}

3:动态表头写入web

private List<List<String>> head() {List<List<String>> list = new ArrayList<List<String>>();List<String> head0 = new ArrayList<String>();head0.add("字符串" + System.currentTimeMillis());List<String> head1 = new ArrayList<String>();head1.add("数字" + System.currentTimeMillis());List<String> head2 = new ArrayList<String>();head2.add("日期" + System.currentTimeMillis());list.add(head0);list.add(head1);list.add(head2);return list;}private List<DemoData> data() {List<DemoData> list = ListUtils.newArrayList();for (int i = 0; i < 10; i++) {DemoData data = new DemoData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}return list;}@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("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());}

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

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

相关文章

现代皮质沙发模型材质编辑

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 当谈到游戏角色的3D模型风格时&#xff0c;有几种不同的风格&#xf…

解决微信小程序中 ‘nbsp;‘ 空格不生效的问题

在微信小程序开发中&#xff0c;我们经常会使用 来表示一个空格。这是因为在 HTML 中&#xff0c;空格会被解析为一个普通字符&#xff0c;而不会产生实际的空白间距。而 是一种特殊的字符实体&#xff0c;它被解析为一个不可见的空格&#xff0c;可以在页面上产生真正的空…

Nginx的Web服务器:HTTP状态码 “413 Request Entity Too Large“ 表示请求实体过大

上传图片的时候Nginx遇到的&#xff1a; 解决办法&#xff1a;设置客户端请求主体&#xff08;body&#xff09;的大小 http {# 其他配置项...# 设置客户端请求主体&#xff08;body&#xff09;的最大大小为20M&#xff08;20兆字节&#xff09;client_max_body_size 20M;# …

持续集成交付CICD:CentOS 7 安装 Nexus 3.63

目录 一、实验 1.CentOS 7 安装Nexus3.63 二、问题 1.安装Nexus报错 2.Nexus启动停止相关命令 一、实验 1.CentOS 7 安装Nexus3.63 &#xff08;1&#xff09;当前操作系统版本&JDK版本 cat /etc/redhat-releasejava -version&#xff08;2&#xff09;下载Nexus新…

Python---继承

1、什么是继承 我们接下来来聊聊Python代码中的“继承”&#xff1a;类是用来描述现实世界中同一组事务的共有特性的抽象模型&#xff0c;但是类也有上下级和范围之分&#xff0c;比如&#xff1a;生物 > 动物 > 哺乳动物 > 灵长型动物 > 人类 > 黄种人 从哲学…

Docker, Docker-compose部署Sonarqube

参考文档 镜像地址: https://hub.docker.com/_/sonarqube/tags Docker部署文档地址 Installing from Docker | SonarQube Docs Docker-compose文档部署地址&#xff1a; Installing from Docker | SonarQube Docs 部署镜像 2.1 docker部署 # 宿主机执行 $. vi /etc/sysctl.conf…

response应用及重定向和request转发

请求和转发&#xff1a; response说明一、response文件下载二、response验证码实现1.前置知识&#xff1a;2.具体实现&#xff1a;3.知识总结 三、response重定向四、request转发五、重定向和转发的区别 response说明 response是指HttpServletResponse,该响应有很多的应用&…

geolife笔记:整理处理单条轨迹

以 数据集笔记 geolife &#xff08;操作篇&#xff09;_geolife数据集-CSDN博客 轨迹为例 1 读取数据 import pandas as pd data pd.read_csv(Geolife Trajectories 1.3/Data//000/Trajectory/20081023025304.plt,headerNone, skiprows6,names[Latitude, Longitude, Not_Im…

JVM常见垃圾回收器

串行垃圾回收器 Serial和Serial Old串行垃圾回收器&#xff0c;是指使用单线程进行垃圾回收&#xff0c;堆内存较小&#xff0c;适合个人电脑 Serial作用于新生代&#xff0c;采用复制算法 Serial Old作用于老年代&#xff0c;采用标记-整理算法 垃圾回收时&#xff0c;只有…

一文讲解如何从 Clickhouse 迁移数据至 DolphinDB

ClickHouse 是 Yandex 公司于2016年开源的 OLAP 列式数据库管理系统&#xff0c;主要用于 WEB 流量分析。凭借面向列式存储、支持数据压缩、完备的 DBMS 功能、多核心并行处理的特点&#xff0c;ClickHouse 被广泛应用于广告流量、移动分析、网站分析等领域。 DolphinDB 是一款…

解决Idea右侧无Maven选项的问题

在创建 Spring / SpringBoot 项目的时候可能会遇到没有 Maven 选项的问题&#xff0c;如下图&#xff1a; 我们通常这样解决&#xff1a;

JPA对数据库修改注意点

同一事务中获取不到修改数据 spring-boot-starter-parent版本2.7.12 Dao Query(value "select * from inventory_list where id in (?1) order by id desc",nativeQuery true) List<InventoryListEntity> getByIds(List<Integer> idList);Modifyin…