相关依赖(pom):
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.6</version>
</dependency>
AnalysisEventListener<T>:
public abstract class AnalysisEventListener<T> implements ReadListener<T> {
// 这是监听器的构造方法,一般我们可以通过构造方法传入一些我们需要在解析excel时使用的数据
//(在这里,AnalysisEventListener<T>实现ReadListener<T>)
public AnalysisEventListener() {}
// 调用invokeHeadMap来获取表头数据
public void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context) {
this.invokeHeadMap(ConverterUtils.convertToStringMap(headMap, context), context);
}
// 获取表头数据
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {}
// 读取条额外信息:批注、超链接、合并单元格信息等
public void extra(CellExtra extra, AnalysisContext context) {}
// 在转换异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。
public void onException(Exception exception, AnalysisContext context) throws Exception {throw exception;}
public boolean hasNext(AnalysisContext context) {return true;}
}
相关常用方法:
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
public class DemoDataListener extends AnalysisEventListener<DemoData> {
private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);
//每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
private static final int BATCH_COUNT = 5;
List<DemoData> list = new ArrayList<DemoData>();
//假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
private DemoDAO demoDAO;
public DemoDataListener() {
// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
demoDAO = new DemoDAO();
}
//如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
public DemoDataListener(DemoDAO demoDAO) {
this.demoDAO = demoDAO;
}
// 这个每一条数据解析都会来调用
@Override
public void invoke(DemoData data, AnalysisContext context) {
list.add(data);
// 在这里进行相关操作
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
list.clear();
}
}
// 所有数据解析完成了 都会来调用
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
//saveData();
}
// 加上存储数据库
private void saveData() {
demoDAO.save(list);
}
Excel表中存在额外信息时
// 读取条额外信息:批注、超链接、合并单元格信息等
@Override
public void extra(CellExtra extra, AnalysisContext context) {
LOGGER.info("读取到了一条额外信息:{}", JSON.toJSONString(extra));
switch (extra.getType()) {
case COMMENT:
LOGGER.info("额外信息是批注,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(), extra.getColumnIndex(),
extra.getText());
break;
case HYPERLINK:
if ("Sheet1!A1".equals(extra.getText())) {
LOGGER.info("额外信息是超链接,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(),
extra.getColumnIndex(), extra.getText());
} else if ("Sheet2!A1".equals(extra.getText())) {
LOGGER.info(
"额外信息是超链接,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{},"
+ "内容是:{}",
extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(),
extra.getLastColumnIndex(), extra.getText());
} else {
Assert.fail("Unknown hyperlink!");
}
break;
case MERGE:
LOGGER.info(
"额外信息是超链接,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{}",
extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(),
extra.getLastColumnIndex());
break;
default:
}
}
//在转换异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。
@Override
public void onException(Exception exception, AnalysisContext context) {
// 如果是某一个单元格的转换异常 能获取到具体行号
// 如果要获取头的信息 配合invokeHeadMap使用
if (exception instanceof ExcelDataConvertException) {
ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
LOGGER.error("第{}行,第{}列解析异常", excelDataConvertException.getRowIndex(),
excelDataConvertException.getColumnIndex());
}
}
}
代码来源:EasyExcel(一)导入excel的分析监听器_Zack_tzh的博客-CSDN博客_easyexcel监听器
个人Demo:
public class DemoDateListener extends AnalysisEventListener<Demo>{
private ststic final Logger LOGGER = LoggerFactory.getLogger(DemoDateListener.class);
private static final BATCH_COUNT = 1;
Demo demo = new Demo();
int count = 0;
boolean headFlag = false;//表头标识
boolean headFlag1 = false;//表头标识
boolean headFlag2 = false;//数字标识
private DemoService demoService;
public DemoListener(DemoService demoservice){
this.demoService=demoService
}
public void invoke(Demo data, AnalysisContext context) {
System.out.println(JSON.toJSONString(data));
if (data.getTest() != null) {
if (data.getTest().equals("实验对象"))
headFlag = true;
}
if (headFlag && headFlag1) {
demo = data;
demo.setExcelType("2");
insertData();
}
if (data.getTest() != null) {
if (data.getTest().equals("实验对象") || data.getTest().equals("实验对象"))
headFlag1 = true;
}
}
public void doAfterAllAnalysed(AnalysisContext context) {
LOGGER.info("所有数据解析完成!");
}
private void insertData() {
}
}
按照需求不同,建立对应的listener。