Springboot + Easyexcel 读取数据

简单读取excel文件

读取下图的 excel 数据

导入依赖,阿里的easyexcel插件

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

创建一个用来 读取 excel的实体类

实体类的属性可以用

@ExcelProperty(index = 0),index=0,找的是上图 A列(第一列)

@ExcelProperty(value = “标号”)

两种都可以用,但是不要两个一起用

实体类:

public class TemplateEntity {@ExcelProperty("标号")private Integer label;@ExcelProperty("字符串")private String str;@ExcelProperty("数字")private Integer num;//getter/setter 省略
}

定义一个 监听类:

public class TemplateListener extends AnalysisEventListener<TemplateEntity> {private List<TemplateEntity> list = new ArrayList<>();// 一条一条读取数据,全部添加到list集合里@Overridepublic void invoke(TemplateEntity data, AnalysisContext analysisContext) {list.add(data);}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {}public List<TemplateEntity> getData() {return list;}
}

service:

public interface TemplateService {/*** 导入excel*/Result importExcel(MultipartFile file) throws IOException;
}@Service
public class TemplateServiceImpl implements TemplateService {@Overridepublic Result importExcel(MultipartFile file) throws IOException{List<TemplateEntity> entities = getTemplateEntities(file);// 处理数据System.out.println(entities);return Result.success(entities);}// 读取 excel 数据private List<TemplateEntity> getTemplateEntities(MultipartFile file) throws IOException {TemplateListener listener = new TemplateListener(); // 定义的 listenerEasyExcel.read(file.getInputStream(), TemplateEntity.class, listener).sheet().doRead();// 返回 所有数据return listener.getData();}
}

Controller 上传文件接口

@RestController
@RequestMapping("/sys")
public class TemplateController {@Autowiredprivate TemplateService templateService;@RequestMapping("/import")public Result importData(@RequestPart("file") MultipartFile file) throws IOException{return templateService.importExcel(file);}
}

Postman测试

{"code": 200,"msg": "处理成功","data": [{"label": 1,"str": "a","num": 20},{"label": 2,"str": "b","num": 30},{"label": 3,"str": "c","num": 40},...
}

日期格式

excel文件

实体类中可以使用@DateFormat(阿里包下的)注解:

要使用String类型来接收数据才有用

public class TemplateEntity {@ExcelProperty("标号")private Integer label;@ExcelProperty("字符串")private String str;@ExcelProperty("数字")private Integer num;@ExcelProperty("时间")// 这里需要用string接收才会格式化@DateTimeFormat("yyyy-MM-dd")private String date;// getter/setter省略
}

多sheet

两sheet表头数据不一致

这里为了演示效果,sheet1和sheet3是不同表头的,sheet2目前是空的数据表

思路:需要再定义一个excel接收数据的实体类,然后创建监听类,重写方法

读取时,指定不同的监听类,excel接收数据的实体类对象,然后放入map中返回即可

具体实现

实体类

TemplateEntity接收sheet1

@Data
public class TemplateEntity {@ExcelProperty("标号")private Integer label;@ExcelProperty("字符串")private String str;@ExcelProperty("数字")private Integer num;@ExcelProperty(value = "时间")@DateTimeFormat("yyyy-MM-dd")private String date;
}

OtherTemplateEntity接收sheet3

@Data
public class OtherTemplateEntity {@ExcelProperty("标号")private String label;@ExcelProperty("名称")private String name;@ExcelProperty("类型")private String type;@ExcelProperty(value = "时间")@DateTimeFormat("yyyy-MM-dd")private String date;
}

监听类

public class TemplateListener extends AnalysisEventListener<TemplateEntity> {private List<TemplateEntity> list = new ArrayList<>();// 一条一条读取数据,全部添加到list集合里@Overridepublic void invoke(TemplateEntity data, AnalysisContext analysisContext) {list.add(data);}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {}public List<TemplateEntity> getData() {return list;}
}public class OtherTemplateListener extends AnalysisEventListener<OtherTemplateEntity> {private List<OtherTemplateEntity> list = new ArrayList<>();@Overridepublic void invoke(OtherTemplateEntity data, AnalysisContext context) {list.add(data);}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {}public List<OtherTemplateEntity> getData() {return list;}
}

controller层

@PostMapping("/importMany")
public R importMany(@RequestPart("file") MultipartFile file) throws IOException {return easyExcelService.importManyExcel(file);
}

service实现层

public R importManyExcel(MultipartFile file) throws IOException {Map<String, Object> map = getTemplateEntitiesMany(file);List<TemplateEntity> data1 = (List<TemplateEntity>) map.get("data1");List<OtherTemplateEntity> data2 = (List<OtherTemplateEntity>) map.get("data2");log.info("data1数据=={}", data1);log.info("data2数据=={}", data2);return R.success(map);
}private Map<String, Object> getTemplateEntitiesMany(MultipartFile file) throws IOException {Map<String,Object> map = new HashMap<>();TemplateListener listener = new TemplateListener();   // 定义的 listenerOtherTemplateListener otherListener = new OtherTemplateListener();ExcelReader excelReader = EasyExcel.read(file.getInputStream()).build();// 这里为了简单 所以注册了 同样的head 和Listener 自己使用功能必须不同的Listener// readSheet参数设置读取sheet的序号// 读取sheet1ReadSheet readSheet1 =EasyExcel.readSheet(0).head(TemplateEntity.class).registerReadListener(listener).build();// 读取sheet3ReadSheet readSheet2 =EasyExcel.readSheet(2).head(OtherTemplateEntity.class).registerReadListener(otherListener).build();excelReader.read(readSheet1, readSheet2);// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的excelReader.finish();// 取出数据放入map中,然后返回List<TemplateEntity> data1 = listener.getData();List<OtherTemplateEntity> data2 = otherListener.getData();map.put("data1", data1);map.put("data2", data2);return map;}

读取结果

{"code": 200,"msg": "OK","message": null,"data": {"data2": [{"label": "a","name": "a1","type": "t1","date": "2022-01-07"},{"label": "b","name": "b1","type": "t2","date": "2022-01-07"}......],"data1": [{"label": 1,"str": "a","num": 20,"date": "2021-12-20"},{"label": 2,"str": "b","num": 30,"date": "2021-12-20"}......]}
}

两sheet表头数据一致

在sheet2加上数据,和sheet1的表头数据一致

具体实现

数据实体类,由于sheet1和sheet2表头一致,故用一个实体类即可

@Data
public class TemplateEntity {@ExcelProperty("标号")private Integer label;@ExcelProperty("字符串")private String str;@ExcelProperty("数字")private Integer num;@ExcelProperty(value = "时间")@DateTimeFormat("yyyy-MM-dd")private String date;
}

监听类

public class TemplateListener extends AnalysisEventListener<TemplateEntity> {private List<TemplateEntity> list = new ArrayList<>();@Overridepublic void invoke(TemplateEntity data, AnalysisContext context) {list.add(data);}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {}public List<TemplateEntity> getData() {return list;}
}

service实现层

这里返回什么根据自己的业务需求,我是把两个sheet的数据分别放在各自的集合里了,也可以都放到一个集合里返回,具体实现看个人需求

@Override
public R importManyExcelEq(MultipartFile file) throws IOException {Map<String, Object> map = getTemplateEntitiesManyEq(file);List<TemplateEntity> data1 = (List<TemplateEntity>) map.get("data1");List<TemplateEntity> data2 = (List<TemplateEntity>) map.get("data2");log.info("data1数据=={}", data1);log.info("data2数据=={}", data2);return R.success(map);
}private Map<String, Object> getTemplateEntitiesManyEq(MultipartFile file) throws IOException {Map<String,Object> map = new HashMap<>();TemplateListener listenerSheet1 = new TemplateListener();   // 定义的 listenerTemplateListener listenerSheet2 = new TemplateListener();ExcelReader excelReader = EasyExcel.read(file.getInputStream()).build();// 这里为了简单 所以注册了 同样的head 和Listener 自己使用功能必须不同的Listener// readSheet参数设置读取sheet的序号// 读取sheet1ReadSheet readSheet1 =EasyExcel.readSheet(0).head(TemplateEntity.class).registerReadListener(listenerSheet1).build();// 读取sheet2ReadSheet readSheet2 =EasyExcel.readSheet(1).head(TemplateEntity.class).registerReadListener(listenerSheet2).build();excelReader.read(readSheet1, readSheet2);// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的excelReader.finish();List<TemplateEntity> data1 = listenerSheet1.getData();List<TemplateEntity> data2 = listenerSheet2.getData();map.put("data1", data1);map.put("data2", data2);return map;
}

读取结果

{"code": 200,"msg": "OK","message": null,"data": {"data2": [{"label": 1,"str": "a2","num": 200,"date": "2022-02-15"},{"label": 2,"str": "b2","num": 300,"date": "2022-02-15"}......],"data1": [{"label": 1,"str": "a","num": 20,"date": "2021-12-20"},{"label": 2,"str": "b","num": 30,"date": "2021-12-20"}......]}
}

多行头

读取时设置头行数即可

headRowNumber是头行数,如下是设置头行数2,那么读取时会从第三行开始读取数据

private List<TemplateEntity> getTemplateEntities(MultipartFile file) throws IOException {TemplateListener listener = new TemplateListener();  // 定义的 listenerEasyExcel.read(file.getInputStream(), TemplateEntity.class, listener).sheet(0).headRowNumber(2).doRead();// 返回 所有数据return listener.getData();}

读取表头数据

在监听类中重写invokeHeadMap方法,将表头数据也添加即可

public class TemplateListener extends AnalysisEventListener<TemplateEntity> {private List<TemplateEntity> list = new ArrayList<>();@Overridepublic void invoke(TemplateEntity data, AnalysisContext context) {list.add(data);}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {}public List<TemplateEntity> getData() {return list;}@Overridepublic void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {// 读取到头数据LOGGER.info("解析到一条头数据:{}", JSON.toJSONString(headMap))}

Springboot + Easyexcel 写入数据

简单导出excel

实体类省略,还是上面的TemplateEntity

导出excel数据,这里有两种写法,拟定好文件名称直接传入方法,会自动创建一个文件

// 模拟数据
private List<TemplateEntity> exportData() {List<TemplateEntity> entities = new ArrayList<>();for (int i = 0; i< 10; i++) {TemplateEntity entity = new TemplateEntity();entity.setStr("字符串" + i);entity.setDate("数据" + i);entity.setLabel(i+1);entity.setNum(i);entities.add(entity);}return entities;
}public R export() {String path = "C:\Users\EDZ\Desktop\";// 写法1String fileName = path + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭// 如果这里想使用03 则 传入excelType参数即可EasyExcel.write(fileName, TemplateEntity.class).sheet("模板").doWrite(exportData());// 写法2// 这里 需要指定写用哪个class去写ExcelWriter excelWriter = EasyExcel.write(fileName, TemplateEntity.class).build();WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();excelWriter.write(exportData(), writeSheet);// 千万别忘记finish 会帮忙关闭流excelWriter.finish();return R.success();
}

写入后的结果

过滤导出列

public R export() {String path = "C:\Users\EDZ\Desktop\";String fileName = path + System.currentTimeMillis() + ".xlsx";// 加入要忽略date字段Set<String> excludeColumnFiledNames = new HashSet<String>();excludeColumnFiledNames.add("date");EasyExcel.write(fileName,TemplateEntity.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板").doWrite(exportData());   }

写入后结果

复杂头写入

实体类

@Data
public class TemplateEntity {@ExcelProperty({"主标题", "标号"})private Integer label;@ExcelProperty({"主标题", "字符串"})private String str;@ExcelProperty({"主标题", "数字"})private Integer num;@ExcelProperty({"主标题", "时间"})@DateTimeFormat("yyyy-MM-dd")private String date;
}

写入后数据

多sheet写入

写入到同一个sheet

@Override
public R export() {String path = "C:\Users\EDZ\Desktop\";String fileName = path + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写ExcelWriter excelWriter = EasyExcel.write(fileName, TemplateEntity.class).build();// 这里注意 如果同一个sheet只要创建一次WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();// 去调用写入,这里我调用了3次,实际使用时根据数据库分页的总的页数来for (int i = 0; i < 3; i++) {// 分页去数据库查询数据 这里可以去数据库查询每一页的数据List<TemplateEntity> data = exportData();excelWriter.write(data, writeSheet);}// 千万别忘记finish 会帮忙关闭流excelWriter.finish();return R.success();
}

写到不同sheet,同一个表头

@Override
public R export() {String path = "C:\Users\EDZ\Desktop\";String fileName = path + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写WriteSheet writeSheet;ExcelWriter excelWriter = EasyExcel.write(fileName, TemplateEntity.class).build();// 去调用写入,这里我调用了三次,实际使用时根据数据库分页的总的页数来。这里最终会写到3个sheet里面for (int i = 0; i < 3; i++) {// 每次都要创建writeSheet 这里注意必须指定sheetNowriteSheet = EasyExcel.writerSheet(i, "模板" + i).build();// 分页去数据库查询数据 这里可以去数据库查询每一页的数据List<TemplateEntity> data = exportData();excelWriter.write(data, writeSheet);}// 千万别忘记finish 会帮忙关闭流excelWriter.finish();return R.success();
}

写入后结果

写到不同sheet,不同的表头

public R export() {String path = "C:\Users\EDZ\Desktop\";String fileName = path + System.currentTimeMillis() + ".xlsx";WriteSheet writeSheet;ExcelWriter excelWriter = EasyExcel.write(fileName).build();// 去调用写入,这里我调用了3次,实际使用时根据数据库分页的总的页数来。这里最终会写到3个sheet里面for (int i = 0; i < 3; i++) {// 我这里 sheet1和sheet2用TemplateEntity类,sheet3用OtherTemplateEntityif (i <= 1) {writeSheet = EasyExcel.writerSheet(i, "模板" + (i + 1)).head(TemplateEntity.class).build();// 分页去数据库查询数据 这里可以去数据库查询每一页的数据List<TemplateEntity> data = exportData();excelWriter.write(data, writeSheet);} else {writeSheet = EasyExcel.writerSheet(i, "模板" + (i + 1)).head(OtherTemplateEntity.class).build();// 分页去数据库查询数据 这里可以去数据库查询每一页的数据List<OtherTemplateEntity> data = exportDataOther();excelWriter.write(data, writeSheet);}}// 千万别忘记finish 会帮忙关闭流excelWriter.finish();return R.success();
}

写入后结果

sheet1(TemplateEntity类的表头)

sheet3(OtherTemplateEntity类的表头)

收工!

先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

Springboot + Easyexcel读取写入数据,多头行数,多sheet,复杂表头简单实现相关推荐

  1. java读取csv文件的行数_JMeter 读取 CSV 文件数据行数

    在用 JMeter 做测试时,经常需要调用外部 CSV 文件的数据到脚本中使用,如果我们想对 CSV 文件中数据的行数进行统计,这个怎么做呢? 针对上面表格的数据,我们一起来学习一下如何统计数据行数吧 ...

  2. Excel 2010 VBA 入门 037 获取最后一行数据的行数

    目录 示例: 实现代码1 使用Find方法查找最后的单元格 Find方法按行查找和按列查找的区别 实现代码2 获取工作表总行数 实现代码3 单元格对象的End属性 End属性的局限性 其他获取最后数据 ...

  3. C#读取excel的有效行数或者最大有效列数

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using NPOI.SS. ...

  4. java读取csv文件行数_java读取巨大csv的行数

    我有超过700K行的巨大csv行数.我必须解析那些csv的行和do ops.我想通过使用线程来做到这一点.我第一次尝试做的很简单.每个线程都应该有唯一的csv行.我只有有限的行数只能读到3000.我创 ...

  5. 用多态来实现U盘,Mp3,移动硬盘和电脑的对接,读取写入数据。

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  6. 代码行数越少就越“简单”吗?

    我们先一起看一个例子.下面这三段代码可以实现同样一个功能:检查输入的字符串 ipAddress 是否是合法的 IP 地址. 一个合法的 IP 地址由四个数字组成,并且通过"."来进 ...

  7. eclipse代码量统计插件_Android Studio 代码行数统计插件Statistic的简单使用

    在项目开发过程中,有时候需要统计代码行数(比如组长想关心一下你的代码量,或者要申请软件著作权时),需要统计的文件类型主要是 .java..xml..kt等,已经有人开发好相关插件了,如果你是用Andr ...

  8. springboot easyexcel导出百万数据优化

    说明 由于某些原因系统jvm内存最大只能给到512,但是要导出百万数据该如何实现呢?传统的一次性导出肯定是不行的 优化 Excel导出基于 springboot , easyexcel 依赖: < ...

  9. spark从hbase读取写入数据

    将RDD写入hbase 注意点: 依赖: 将lib目录下的hadoop开头jar包.hbase开头jar包添加至classpath 此外还有lib目录下的:zookeeper-3.4.6.jar.me ...

最新文章

  1. ubuntu 14.04 64 bit上开启nscd服务缓存加速及清除dns缓存
  2. 每天一个linux命令(12):more命令
  3. 读《大话设计模式》有感
  4. 多线程-Thread-Runnable
  5. 【干货】普华永道:新形势下,企业如何进行数字化转型.pdf(附下载链接)
  6. sql 左侧要固定最近一周的周四 怎么写_数据与IT人怎么提高公司地位,避免被业务当工具人?...
  7. 表达式二叉树(蛋疼ing)
  8. python基本文件操作
  9. 传智播客 C/C++学习笔记 内存四区模型
  10. java.lang.IllegalStateException: Only fullscreen activities can request orientation
  11. Modem Device on High Definition Audio Bus
  12. python熄灯问题
  13. php手机接收验证码,乐信揭秘php手机接收短信验证码实现编程案例
  14. NLP模型笔记2022-11:CTB5和CTB8数据集预处理 【PennTreebank 和Chinese Treebank】
  15. EasyExcel删除模版Sheet页
  16. 【Rust日报】2021-12-15 - geoping 由 shodan 开发的多地 ping 工具
  17. 软件项目经理,如何确保项目管理三大目标(质量、进度、成本)的达成?
  18. 如何关闭Mysql后台运行
  19. 透视映客半年报:亏损背后的长期价值
  20. Android 11获取应用列表 android.permission.QUERY_ALL_PACKAGES

热门文章

  1. 如何将汉语拼音转换为音素+声调数字
  2. Java人事与工资管理系统的设计
  3. maven clean install报系统资源不足
  4. df,lsblk,fdisk命令区别
  5. 屏幕录像软件哪个好用?
  6. 文章聚合怎么进行文章伪原创
  7. linux u盘加载阵列卡驱动步骤,Linux操作系统U盘加载阵列卡驱动步骤.doc
  8. QQ中强制和他人聊天的代码
  9. 阿哈罗诺夫——玻姆效应(AB效应)
  10. “三秦”项羽史缘谈:项羽不仅是英雄,还是仁者