溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

easyexcel怎么讀取excel合并單元格數(shù)據(jù)

發(fā)布時(shí)間:2023-05-04 15:52:07 來(lái)源:億速云 閱讀:296 作者:iii 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要介紹“easyexcel怎么讀取excel合并單元格數(shù)據(jù)”,在日常操作中,相信很多人在easyexcel怎么讀取excel合并單元格數(shù)據(jù)問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”easyexcel怎么讀取excel合并單元格數(shù)據(jù)”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

普通的excel列表,easyexcel讀取是沒(méi)有什么問(wèn)題的。但是,如果有合并單元格,那么它讀取的時(shí)候,能獲取數(shù)據(jù),但是數(shù)據(jù)是不完整的。如下所示的單元格數(shù)據(jù):

easyexcel怎么讀取excel合并單元格數(shù)據(jù)

    我們通過(guò)簡(jiǎn)單的異步讀取,最后查看數(shù)據(jù)內(nèi)容:

  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("學(xué)生姓名")
    private String name;
    @ExcelProperty("年齡")
    private int age;
    @ExcelProperty("性別")
    private String gender;
    @ExcelProperty({"課程", "課程名稱(chēng)"})
    private String courseName;
    @ExcelProperty({"課程", "分?jǐn)?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());
    }
}

    運(yùn)行程序,打印日志信息如下:

easyexcel怎么讀取excel合并單元格數(shù)據(jù)

   獲取了6個(gè)數(shù)據(jù)沒(méi)錯(cuò),但是每一個(gè)合并單元格記錄里面都有一個(gè)數(shù)據(jù)獲取是空的。

    解決辦法就是需要在異步讀取數(shù)據(jù)監(jiān)聽(tīng)器里面讀取合并單元格的額外數(shù)據(jù),并把這部分?jǐn)?shù)據(jù)給補(bǔ)充上。

    需要修改的地方:

    1、實(shí)體需要增加注解索引值:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ExcelData {
    @ExcelProperty(value = "學(xué)生姓名", index = 0)
    private String name;
    @ExcelProperty(value = "年齡", index = 1)
    private int age;
    @ExcelProperty(value = "性別", index = 2)
    private String gender;
    @ExcelProperty(value = {"課程", "課程名稱(chēng)"}, index = 3)
    private String courseName;
    @ExcelProperty(value = {"課程", "分?jǐn)?shù)"}, index = 4)
    private double score;
}

   2、自定義監(jiān)聽(tīng)器,讀取合并單元格數(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、通過(guò)監(jiān)聽(tīng)器讀取數(shù)據(jù),通過(guò)監(jiān)聽(tīng)器獲取數(shù)據(jù)和合并單元格數(shù)據(jù),然后設(shè)置單元格數(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);
            //設(shè)置值
            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("設(shè)置合并單元格的值異常:{}", 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("設(shè)置合并單元格的初始值異常:{}", e.getMessage());
                    }
                }
            }
        }
        return filedValue;
    }
}

    有個(gè)小細(xì)節(jié)需要注意,我們?cè)谕ㄟ^(guò)監(jiān)聽(tīng)器讀取的時(shí)候,還需要額外讀取合并單元格部分。

EasyExcel.read(FILEPATH, ExcelData.class, listener).extraRead(CellExtraTypeEnum.MERGE).sheet().doRead();

    還有個(gè)小細(xì)節(jié),就是我們的表格一般都是有頭的,頭的內(nèi)容可能是2行,可能是1行,在進(jìn)行合并單元格處理的時(shí)候,需要考慮這個(gè)行數(shù)。我們定義了一個(gè)常量HEAD_ROW_NUM來(lái)記錄這個(gè)行數(shù),最后進(jìn)行單元格值計(jì)算的時(shí)候傳入。 

    我在處理excel數(shù)據(jù)中發(fā)現(xiàn),如果這個(gè)單元格合并,是由我們的程序自己做的,那么它讀取的時(shí)候,是沒(méi)有問(wèn)題的。在上面為null的地方,它其實(shí)都有值:

easyexcel怎么讀取excel合并單元格數(shù)據(jù)

    但是在實(shí)際中,我們的excel不能保證不被人為編輯,那么就很有可能,我們?cè)谶M(jìn)行合并單元格的時(shí)候,把有值和無(wú)值合并到一起,最后就出現(xiàn)前面提到的讀取合并單元格出現(xiàn)數(shù)據(jù)缺失的問(wèn)題。 而我們期望,合并單元格部分他們的數(shù)據(jù)應(yīng)該是一樣的。

到此,關(guān)于“easyexcel怎么讀取excel合并單元格數(shù)據(jù)”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI