您好,登錄后才能下訂單哦!
這篇文章主要介紹“easyexcel怎么讀取excel合并單元格數據”,在日常操作中,相信很多人在easyexcel怎么讀取excel合并單元格數據問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”easyexcel怎么讀取excel合并單元格數據”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
普通的excel列表,easyexcel讀取是沒有什么問題的。但是,如果有合并單元格,那么它讀取的時候,能獲取數據,但是數據是不完整的。如下所示的單元格數據:
我們通過簡單的異步讀取,最后查看數據內容:
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({"課程", "分數"}) 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個數據沒錯,但是每一個合并單元格記錄里面都有一個數據獲取是空的。
解決辦法就是需要在異步讀取數據監聽器里面讀取合并單元格的額外數據,并把這部分數據給補充上。
需要修改的地方:
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 = {"課程", "分數"}, index = 4) private double score; }
2、自定義監聽器,讀取合并單元格數據:
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、通過監聽器讀取數據,通過監聽器獲取數據和合并單元格數據,然后設置單元格數據。
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; } }
有個小細節需要注意,我們在通過監聽器讀取的時候,還需要額外讀取合并單元格部分。
EasyExcel.read(FILEPATH, ExcelData.class, listener).extraRead(CellExtraTypeEnum.MERGE).sheet().doRead();
還有個小細節,就是我們的表格一般都是有頭的,頭的內容可能是2行,可能是1行,在進行合并單元格處理的時候,需要考慮這個行數。我們定義了一個常量HEAD_ROW_NUM來記錄這個行數,最后進行單元格值計算的時候傳入。
我在處理excel數據中發現,如果這個單元格合并,是由我們的程序自己做的,那么它讀取的時候,是沒有問題的。在上面為null的地方,它其實都有值:
但是在實際中,我們的excel不能保證不被人為編輯,那么就很有可能,我們在進行合并單元格的時候,把有值和無值合并到一起,最后就出現前面提到的讀取合并單元格出現數據缺失的問題。 而我們期望,合并單元格部分他們的數據應該是一樣的。
到此,關于“easyexcel怎么讀取excel合并單元格數據”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。