使用EasyExcel實現(xiàn)簡單的Excel表格解析操作
前言
本文記錄了如何使用EasyExcel完成簡單的表格解析操作,同時實現(xiàn)了大量數(shù)據(jù)情況下數(shù)據(jù)的分次批量入庫,并記錄每條數(shù)據(jù)入庫的狀態(tài),以便進行結果統(tǒng)計。
固定模板及表數(shù)據(jù)格式的解析
實現(xiàn)Excel模板內(nèi)容對應的實體類
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serializable;
@Data
@ColumnWidth(24)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class RuleExcel implements Serializable {
private static final long serialVersionUID = 1L;
// 被該注解修飾的實體類中的屬性值,會作為excel對應的標題頭文字
@ExcelProperty(value = "規(guī)則名稱")
private String name;
// 被該注解修飾的實體類中的屬性,會在excel與實體類的轉換中被忽略
// 該變量用于標記該條實體類是否成功入庫,在入庫后操作后更新值為true
@ExcelIgnore
private boolean isSuccess;
}實現(xiàn)AnalysisEventListener監(jiān)聽類
為需要讀取的Excel新建一個監(jiān)聽類,用于專門處理該類型數(shù)據(jù)的Excel,數(shù)據(jù)庫的解析邏輯主要都放在這里邊。
@Data
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class RuleExcelImportListener extends AnalysisEventListener<RuleExcel> {
/**
* 默認每隔500條存儲數(shù)據(jù)庫
*/
private int batchCount = 500;
/**
* 緩存的數(shù)據(jù)列表
*/
private List<RuleExcel> list = new ArrayList<>();
/**
* service
*/
private final IRuleExcelService RuleExcelService;
// 解析表頭
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
List<String> titleList = new ArrayList<>();
try {
// 獲取必要表頭列數(shù)據(jù)
// 獲取目標屬性上@ExcelProperty的值,即屬性的中文名稱
String[] nameValue = AnnotationUtil.getAnnotationValue(RuleExcel.class.getDeclaredField("name"), ExcelProperty.class);
titleList.add(nameValue[0]);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 檢測獲取到的Excel標題頭是否合法
for (String title : titleList) {
boolean isExist = false;
for (Integer i : headMap.keySet()) {
if (title.equals(headMap.get(i))) {
isExist = true;
}
}
if (!isExist) {
throw new ExcelAnalysisException("模版標題不允許修改");
}
}
}
// 解析表格內(nèi)容,一行就是一個RuleExcel實體類
@Override
public void invoke(RuleExcel RuleExcel, AnalysisContext analysisContext) {
// 數(shù)據(jù)合法性校驗
if (String.isEmpty(RuleExcel.getName()) {
throw new ExcelAnalysisException("導入失敗,必填項按要求填寫");
}
list.add(RuleExcel);
// 數(shù)據(jù)入庫2:
// 如果表格數(shù)據(jù)量很大,可以設定暫存數(shù)據(jù)量閾值,當現(xiàn)存list數(shù)量超過閾值后,會先向數(shù)據(jù)庫中存入一批數(shù)據(jù)、清空內(nèi)存后再繼續(xù)解析
// 達到BATCH_COUNT,則調用importer方法入庫,防止數(shù)據(jù)幾萬條數(shù)據(jù)在內(nèi)存,容易OOM
if (list.size() >= batchCount) {
// 調用importer方法
RuleExcelService.importRuleExcel(list);
// 存儲完成清理list
list.clear();
}
}
// 將所有的表格行數(shù)據(jù)解析完畢后會執(zhí)行該方法
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
// 數(shù)據(jù)入庫1:
// 一般來說,如果確定表格數(shù)據(jù)量不大,那么可以在解析完全部excel數(shù)據(jù)后進行數(shù)據(jù)入庫操作
RuleExcelService.importRuleExcel(list);
// 存儲完成清理list
list.clear();
}
}調用方法示例
public void importRuleExcel(MultipartFile file) {
// 文件后綴檢查
CommonUtil.checkImportFile(file.getOriginalFilename());
InputStream inputStream;
// 存儲表格解析結果
List<RuleExcel> ruleExcels = new ArrayList<>();
try {
// 將Service層變量作為依賴傳入
RuleImportListener importListener = new RuleImportListener(ruleService);
inputStream = new BufferedInputStream(file.getInputStream());
// EasyExcel.read()傳入:InputStream, 表格數(shù)據(jù)實體類,表格數(shù)據(jù)實體類監(jiān)聽器
ExcelReaderBuilder builder = EasyExcel.read(inputStream, RuleExcel.class, importListener);
// 執(zhí)行同步解析操作并返回解析結果
ruleExcels = builder.doReadAllSync();
} catch (Exception e) {
throw new ServiceException(e.getMessage());
}
// 導入成功的列表
List<RuleExcel> successList = ruleExcels .stream().filter(RuleExcel::isSuccess).collect(Collectors.toList());
}非固定模板及非固定表數(shù)據(jù)格式的解析
有時候需要讀取的模板并不是固定的、實現(xiàn)聲明好的列,對應的數(shù)據(jù)也不能解析成某個固定的實體類,這個時候就需要我們讀取表的原始解析數(shù)據(jù),并自行進行后續(xù)操作。
// EasyExcel.read()傳入:InputStream, 表格數(shù)據(jù)實體類,表格數(shù)據(jù)實體類監(jiān)聽器 // headRowNumber()傳入:表頭行的所在行數(shù) List<Map<Integer, String>> resultList = EasyExcelUtil.getEasyExcelReaderBuilder(file.getInputStream, null, null) .headRowNumber(0).doReadAllSync(); // resultList 中存儲的就是自0行開始解析到的所有數(shù)據(jù)
到此這篇關于使用EasyExcel實現(xiàn)簡單的Excel表格解析操作的文章就介紹到這了,更多相關EasyExcel解析Excel表格內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Springboot中MyBatisplus使用IPage和Page分頁的實例代碼
這篇文章主要介紹了Springboot中MyBatisplus使用IPage和Page分頁,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12
SpringBoot+@EnableScheduling使用定時器的常見案例
項目開發(fā)中經(jīng)常需要執(zhí)行一些定時任務,本文主要介紹了SpringBoot+@EnableScheduling使用定時器的常見案例,具有一定的參考價值,感興趣的可以了解一下2023-09-09
解析Spring RestTemplate必須搭配MultiValueMap的理由
本文給大家介紹Spring RestTemplate必須搭配MultiValueMap的理由,本文通過實例圖文相結合給大家介紹的非常詳細,需要的朋友參考下吧2021-11-11

