管方文檔
讀取多個sheet的方法
主要代碼
ByteArrayInputStream is = new ByteArrayInputStream(new byte[1024]);
EasyExcel.read(is, new ExcelListener())
.excelType(ExcelTypeEnum.XLSX)
.doReadAll();
監聽器(ExcelListener)
- 需要自定義監聽器
- 每個sheet讀取一次,監聽器會運行一次(創建一個監聽器對象)
- 我們 extends AnalysisEventListener<Map<Integer, Object>> 的監聽器,可以讓導入的數據有編號,而且是map格式的,就不用java對象去接收
package com.cc.eed.service.impl;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.listener.ReadListener;
import java.util.Map;
/**
* <p></p>
*
* @author --
* @since 2024/12/25
*/
public class ExcelListener extends AnalysisEventListener<Map<Integer, Object>> {
//可以獲取當前sheet的名字,最開始執行
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
super.invokeHeadMap(headMap, context);
}
//讀取數據,有一條運行一次
@Override
public void invoke(Map<Integer, Object> integerObjectMap, AnalysisContext analysisContext) {
}
//解析完當前sheet運行
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
監聽器,可以參考管網的:最簡單的監聽器
// 有個很重要的點 DemoDataListener 不能被spring管理,要每次讀取excel都要new,然后里面用到spring可以構造方法傳進去
@Slf4j
public class DemoDataListener implements ReadListener<DemoData> {
/**
* 每隔5條存儲數據庫,實際使用中可以100條,然后清理list ,方便內存回收
*/
private static final int BATCH_COUNT = 100;
/**
* 緩存的數據
*/
private List<DemoData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
/**
* 假設這個是一個DAO,當然有業務邏輯這個也可以是一個service。當然如果不用存儲這個對象沒用。
*/
private DemoDAO demoDAO;
public DemoDataListener() {
// 這里是demo,所以隨便new一個。實際使用如果到了spring,請使用下面的有參構造函數
demoDAO = new DemoDAO();
}
/**
* 如果使用了spring,請使用這個構造方法。每次創建Listener的時候需要把spring管理的類傳進來
*
* @param demoDAO
*/
public DemoDataListener(DemoDAO demoDAO) {
this.demoDAO = demoDAO;
}
/**
* 這個每一條數據解析都會來調用
*
* @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
*/
@Override
public void invoke(DemoData data, AnalysisContext context) {
log.info("解析到一條數據:{}", JSON.toJSONString(data));
cachedDataList.add(data);
// 達到BATCH_COUNT了,需要去存儲一次數據庫,防止數據幾萬條數據在內存,容易OOM
if (cachedDataList.size() >= BATCH_COUNT) {
saveData();
// 存儲完成清理 list
cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
}
/**
* 所有數據解析完成了 都會來調用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 這里也要保存數據,確保最后遺留的數據也存儲到數據庫
saveData();
log.info("所有數據解析完成!");
}
/**
* 加上存儲數據庫
*/
private void saveData() {
log.info("{}條數據,開始存儲數據庫!", cachedDataList.size());
demoDAO.save(cachedDataList);
log.info("存儲數據庫成功!");
}
}