前言
EaxyExcel不仅导出多个sheet页,还可以读取多个sheet。核心是为每个sheet分别配置监听器。
效果
实现
导入依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1-jre</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- springboot test启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
继承AnalysisEventListener类
EaxyExcel读取excel采用监听者模式,监听器的命名以Listener结尾。要实现的是invoke和doAfterAllAnalysed方法。
EaxyExcel每读一行数据都调用invoke方法,读完当前sheet后调用doAfterAllAnalysed。
AnalysisEventListener是个泛型类,假设传入的泛型是Map<Integer, String>,那就取到每个格子的列号和值,再配合invoke的参数,可以拿到行号。列号和行号都有了,干啥不行?
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.util.*;
/**
* 不能交给spring管理,每次读取都要new
*
* @date 12/23/2020 18:52
*/
@Slf4j
@Data
public class LunchDataListenerMultiSheetForCSDN extends AnalysisEventListener<Map<Integer, String>> {
private List<List<String>> dataList;
public LunchDataListenerMultiSheetForCSDN() {
this.dataList = new ArrayList<>();
}
/**
* 每读到一行数据都调用invoke方法
*
* @param integerObjectMap
* @param context
*/
@Override
public void invoke(Map<Integer, String> integerObjectMap, AnalysisContext context) {
Integer rowIndex = context.readRowHolder().getRowIndex();
System.out.println("rowIndex = " + rowIndex);
// key为列号,value为单元格的内容
log.info("解析到数据:{}", integerObjectMap);
// 把数据放到dataList里面,便于统一处理
LinkedList<String> strings = new LinkedList<>();
integerObjectMap.forEach((k,v) -> {
strings.add(v);
});
this.dataList.add(strings);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
// 读完所有数据,做统一处理。
// 当然还可以拿到listener之外处理
log.info("数据读取完成");
}
}
单元测试
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.ArrayList;
/**
* https://www.cjavapy.com/mip/486/
* Java 使用EasyExcel读取Excel中多个sheet方法及示例代码
* <p>
* csdn
*
* @date 01/22/2021 04:06
*/
@Slf4j
public class ReadDemo3MultiSheetForCSDN {
/**
* 读取多个sheet
*/
@Test
public void test1() {
// 读取已经填好的模板
String fileName = "/Users/quanlinglong/Downloads/mergeDemo/demo1611758627138.xlsx";
// 读取带下拉框的表格
System.out.println("fileName = " + fileName);
ExcelReader excelReader =
EasyExcel.read(fileName).build();
// 每个sheet分别创建监听器
LunchDataListenerMultiSheetForCSDN listener0 = new LunchDataListenerMultiSheetForCSDN();
LunchDataListenerMultiSheetForCSDN listener1 = new LunchDataListenerMultiSheetForCSDN();
ReadSheet readSheet0 =
EasyExcel.readSheet(0).registerReadListener(listener0).build();
ReadSheet readSheet1 =
EasyExcel.readSheet(1).registerReadListener(listener1).build();
// 这里注意 一定要把sheet1 sheet2 一起传进去,不然有个问题就是03版的excel 会读取多次,浪费性能
// 可以传多个ReadSheet对象,读多个sheet
excelReader.read(readSheet0, readSheet1);
// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
excelReader.finish();
ArrayList<LunchDataListenerMultiSheetForCSDN> listenerList = new ArrayList<>();
listenerList.add(listener0);
listenerList.add(listener1);
for (LunchDataListenerMultiSheetForCSDN listener : listenerList) {
// 从listtener中取出内容
listener.getDataList().forEach(lineData -> {
System.out.println("lineData = " + lineData);
// 其它业务处理。。
});
}
}
}
拿到当前sheet的数据要在哪里处理呢?在doAfterAllAnalysed处理,也可以读取所有后统一处理,本文用后一种思路。具体在哪里处理,结合你的业务需求灵活处理。
相关链接:
Java 使用EasyExcel读取Excel中多个sheet方法及示例代码
希望对你有用