easyexcel讀取excel合并單元格數(shù)據(jù)的操作代碼
普通的excel列表,easyexcel讀取是沒有什么問題的。但是,如果有合并單元格,那么它讀取的時候,能獲取數(shù)據(jù),但是數(shù)據(jù)是不完整的。如下所示的單元格數(shù)據(jù):
我們通過簡單的異步讀取,最后查看數(shù)據(jù)內容:
ExcelData.java
package com.example.model; import com.alibaba.excel.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class ExcelData { @ExcelProperty("學生姓名") private String name; @ExcelProperty("年齡") private int age; @ExcelProperty("性別") private String gender; @ExcelProperty({"課程", "課程名稱"}) private String courseName; @ExcelProperty({"課程", "分數(shù)"}) private double score; }
ExcelRead.java
package com.example.service; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.example.model.ExcelData; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.List; @Slf4j public class ExcelRead { private static final String FILEPATH = "e:\\test\\student.xlsx"; public List<ExcelData> list() { List<ExcelData> excelDataList = new ArrayList<>(); EasyExcel.read(FILEPATH, ExcelData.class, new AnalysisEventListener<ExcelData>() { @Override public void invoke(ExcelData excelData, AnalysisContext analysisContext) { log.info("read data {}", excelData); excelDataList.add(excelData); } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } }).sheet().doRead(); return excelDataList; } }
ExcelTest.java
package com.example.service; import com.example.model.ExcelData; import java.util.List; public class ExcelTest { public static void main(String[] args) { ExcelRead excelRead = new ExcelRead(); List<ExcelData> list = excelRead.list(); System.out.println(list.size()); } }
運行程序,打印日志信息如下:
獲取了6個數(shù)據(jù)沒錯,但是每一個合并單元格記錄里面都有一個數(shù)據(jù)獲取是空的。
解決辦法就是需要在異步讀取數(shù)據(jù)監(jiān)聽器里面讀取合并單元格的額外數(shù)據(jù),并把這部分數(shù)據(jù)給補充上。
需要修改的地方:
1、實體需要增加注解索引值:
@Data @AllArgsConstructor @NoArgsConstructor public class ExcelData { @ExcelProperty(value = "學生姓名", index = 0) private String name; @ExcelProperty(value = "年齡", index = 1) private int age; @ExcelProperty(value = "性別", index = 2) private String gender; @ExcelProperty(value = {"課程", "課程名稱"}, index = 3) private String courseName; @ExcelProperty(value = {"課程", "分數(shù)"}, index = 4) private double score; }
2、自定義監(jiān)聽器,讀取合并單元格數(shù)據(jù):
package com.example.service; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.enums.CellExtraTypeEnum; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.metadata.CellExtra; import com.example.model.ExcelData; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.List; @Slf4j public class CustomAnalysisEventListener extends AnalysisEventListener<ExcelData> { private int headRowNum; public CustomAnalysisEventListener(int headRowNum) { this.headRowNum = headRowNum; } private List<ExcelData> list = new ArrayList<>(); private List<CellExtra> cellExtraList = new ArrayList<>(); @Override public void invoke(ExcelData excelData, AnalysisContext analysisContext) { log.info(" data -> {}", excelData); list.add(excelData); } @Override public void extra(CellExtra extra, AnalysisContext context) { CellExtraTypeEnum type = extra.getType(); switch (type) { case MERGE: { if (extra.getRowIndex() >= headRowNum) { cellExtraList.add(extra); } break; } default:{ } } } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } public List<ExcelData> getList() { return list; } public List<CellExtra> getCellExtraList() { return cellExtraList; } }
3、通過監(jiān)聽器讀取數(shù)據(jù),通過監(jiān)聽器獲取數(shù)據(jù)和合并單元格數(shù)據(jù),然后設置單元格數(shù)據(jù)。
package com.example.service; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.enums.CellExtraTypeEnum; import com.alibaba.excel.metadata.CellExtra; import com.example.model.ExcelData; import lombok.extern.slf4j.Slf4j; import java.lang.reflect.Field; import java.util.List; @Slf4j public class ExcelRead { private static final int HEAD_ROW_NUM = 2; private static final String FILEPATH = "e:\\test\\student.xlsx"; public List<ExcelData> list() { List<ExcelData> excelDataList; CustomAnalysisEventListener listener = new CustomAnalysisEventListener(HEAD_ROW_NUM); EasyExcel.read(FILEPATH, ExcelData.class, listener).extraRead(CellExtraTypeEnum.MERGE).sheet().doRead(); excelDataList = listener.getList(); List<CellExtra> cellExtraList = listener.getCellExtraList(); if (cellExtraList != null && cellExtraList.size() > 0) { mergeExcelData(excelDataList, cellExtraList, HEAD_ROW_NUM); } return excelDataList; } private void mergeExcelData(List<ExcelData> excelDataList, List<CellExtra> cellExtraList, int headRowNum) { cellExtraList.forEach(cellExtra -> { int firstRowIndex = cellExtra.getFirstRowIndex() - headRowNum; int lastRowIndex = cellExtra.getLastRowIndex() - headRowNum; int firstColumnIndex = cellExtra.getFirstColumnIndex(); int lastColumnIndex = cellExtra.getLastColumnIndex(); //獲取初始值 Object initValue = getInitValueFromList(firstRowIndex, firstColumnIndex, excelDataList); //設置值 for (int i = firstRowIndex; i <= lastRowIndex; i++) { for (int j = firstColumnIndex; j <= lastColumnIndex; j++) { setInitValueToList(initValue, i, j, excelDataList); } } }); } private void setInitValueToList(Object filedValue, Integer rowIndex, Integer columnIndex, List<ExcelData> data) { ExcelData object = data.get(rowIndex); for (Field field : object.getClass().getDeclaredFields()) { field.setAccessible(true); ExcelProperty annotation = field.getAnnotation(ExcelProperty.class); if (annotation != null) { if (annotation.index() == columnIndex) { try { field.set(object, filedValue); break; } catch (IllegalAccessException e) { log.error("設置合并單元格的值異常:{}", e.getMessage()); } } } } } private Object getInitValueFromList(Integer firstRowIndex, Integer firstColumnIndex, List<ExcelData> data) { Object filedValue = null; ExcelData object = data.get(firstRowIndex); for (Field field : object.getClass().getDeclaredFields()) { field.setAccessible(true); ExcelProperty annotation = field.getAnnotation(ExcelProperty.class); if (annotation != null) { if (annotation.index() == firstColumnIndex) { try { filedValue = field.get(object); break; } catch (IllegalAccessException e) { log.error("設置合并單元格的初始值異常:{}", e.getMessage()); } } } } return filedValue; } }
有個小細節(jié)需要注意,我們在通過監(jiān)聽器讀取的時候,還需要額外讀取合并單元格部分。
EasyExcel.read(FILEPATH, ExcelData.class, listener).extraRead(CellExtraTypeEnum.MERGE).sheet().doRead();
還有個小細節(jié),就是我們的表格一般都是有頭的,頭的內容可能是2行,可能是1行,在進行合并單元格處理的時候,需要考慮這個行數(shù)。我們定義了一個常量HEAD_ROW_NUM來記錄這個行數(shù),最后進行單元格值計算的時候傳入。
我在處理excel數(shù)據(jù)中發(fā)現(xiàn),如果這個單元格合并,是由我們的程序自己做的,那么它讀取的時候,是沒有問題的。在上面為null的地方,它其實都有值:
但是在實際中,我們的excel不能保證不被人為編輯,那么就很有可能,我們在進行合并單元格的時候,把有值和無值合并到一起,最后就出現(xiàn)前面提到的讀取合并單元格出現(xiàn)數(shù)據(jù)缺失的問題。 而我們期望,合并單元格部分他們的數(shù)據(jù)應該是一樣的。所以今天的解決方案是一種保險的做法,不管你的表格是否有合并單元格,是否人為修改,最終都能把合并單元格缺失的數(shù)據(jù)進行恢復。
到此這篇關于easyexcel讀取excel合并單元格數(shù)據(jù)的操作代碼的文章就介紹到這了,更多相關easyexcel合并單元格數(shù)據(jù)內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot配置數(shù)據(jù)庫密碼加密的方法
由于系統(tǒng)安全的考慮,配置文件中不能出現(xiàn)明文密碼的問題,本文就給大家詳細介紹下springboot配置數(shù)據(jù)庫密碼加密的方法,下面話不多說了,來一起看看詳細的介紹吧,需要的朋友可以參考下2023-08-08Spring的BeanFactoryPostProcessor接口示例代碼詳解
這篇文章主要介紹了Spring的BeanFactoryPostProcessor接口,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02