All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gitee.ludii.excel.read.reader.SheetReader Maven / Gradle / Ivy

package io.gitee.ludii.excel.read.reader;

import io.gitee.ludii.excel.converts.ConverterKeyBuild;
import io.gitee.ludii.excel.converts.NoneReadConverter;
import io.gitee.ludii.excel.converts.ReadConverter;
import io.gitee.ludii.excel.enums.CellDataTypeEnum;
import io.gitee.ludii.excel.enums.SheetHeadModel;
import io.gitee.ludii.excel.exceptions.ExcelException;
import io.gitee.ludii.excel.read.metadata.config.SheetReaderConfigItemDefinition;
import io.gitee.ludii.excel.read.metadata.config.SheetReaderConfigMainDefinition;
import io.gitee.ludii.excel.read.metadata.data.ReadCellData;
import io.gitee.ludii.excel.utils.CommonUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import java.util.*;

/**
 * @author 陆迪
 * @date 2022/4/24
 */
public class SheetReader {

    private final WorkbookReader workbookReader;


    private final Sheet sheet;

    /**
     * 数据开始行.前一行为标题行
     * 若值为0,则表示无标题栏.
     * 默认无标题
     */
    private final int dataRowStartIndex;

    /**
     * 数据开始列
     * 默认从0开始
     */
    private final int dataColumnStartIndex;

    /**
     * 解析配置
     */
    private final SheetReaderConfigMainDefinition sheetReaderConfigMainDefinition;

    private final Map> readConverterMap;

    private Map, ReadConverter> readConverterClazzMap;

    private final CellReader cellReader;

    /**
     * key是列索引的下标,即columnNumber
     */
    private Map> sortHeadReadCellDataMap;

    private Map> titleHeadReadCellDataMap;


    SheetReader(WorkbookReader workbookReader
            , int sheetIndex
            , Integer dataRowStartIndex
            , Integer dataColumnStartIndex
            , SheetReaderConfigMainDefinition sheetReaderConfigMainDefinition,
                Map> readConverterMap) {
        this.workbookReader = workbookReader;
        this.sheet = this.workbookReader.getWorkbook().getSheetAt(sheetIndex);
        this.dataRowStartIndex = dataRowStartIndex != null ? dataRowStartIndex : sheetReaderConfigMainDefinition.getDataRowStartIndex();
        this.dataColumnStartIndex = dataColumnStartIndex != null ? dataColumnStartIndex : sheetReaderConfigMainDefinition.getDataColumnStartIndex();
        this.sheetReaderConfigMainDefinition = sheetReaderConfigMainDefinition;
        this.readConverterMap = readConverterMap;
        this.cellReader = new CellReader(this.workbookReader.getFormulaEvaluator());

        sheetReaderConfigMainDefinition.getItemDefinitionList().sort(Comparator.comparing(SheetReaderConfigItemDefinition::getSort));
    }

    SheetReader(WorkbookReader workbookReader
            , String sheetName
            , Integer dataRowStartIndex
            , Integer dataColumnStartIndex
            , SheetReaderConfigMainDefinition sheetReaderConfigMainDefinition, Map> readConverterMap) {
        this.workbookReader = workbookReader;
        this.sheet = this.workbookReader.getWorkbook().getSheet(sheetName);
        this.dataRowStartIndex = dataRowStartIndex != null ? dataRowStartIndex : sheetReaderConfigMainDefinition.getDataRowStartIndex();
        this.dataColumnStartIndex = dataColumnStartIndex != null ? dataColumnStartIndex : sheetReaderConfigMainDefinition.getDataColumnStartIndex();
        this.sheetReaderConfigMainDefinition = sheetReaderConfigMainDefinition;
        this.readConverterMap = readConverterMap;
        this.cellReader = new CellReader(this.workbookReader.getFormulaEvaluator());

        sheetReaderConfigMainDefinition.getItemDefinitionList().sort(Comparator.comparing(SheetReaderConfigItemDefinition::getSort));
    }


    public List readAll() {
        return this.readData();
    }

    private int getFirstRowNum() {
        return this.sheet.getFirstRowNum();
    }

    private int getLasRowNum() {
        return this.sheet.getLastRowNum();
    }

    private int getHeadRowIndex() {
        return dataRowStartIndex - 1;
    }

    private int getDataRowStartIndex() {
        return dataRowStartIndex;
    }

    private int getDataColumnStartIndex() {
        return dataColumnStartIndex;
    }

    private void readHead() {
        int firstRowNum = this.getFirstRowNum();
        int headRowIndex = this.getHeadRowIndex();

        if (headRowIndex == -1 || headRowIndex < firstRowNum) {
            this.sortHeadReadCellDataMap = Collections.emptyMap();
            return;
        }
        Row row = this.getRow(headRowIndex);
        this.sortHeadReadCellDataMap = this.readRow(row);
    }

    private List readData() {
        int dataRowStartIndex = this.getDataRowStartIndex();
        int firstRowNum = this.getFirstRowNum();
        int startRowIndex = Math.max(dataRowStartIndex, firstRowNum);

        int lasRowNum = this.getLasRowNum();

        List resultDataList = new ArrayList<>();
        for (int rowIndex = startRowIndex; rowIndex <= lasRowNum; rowIndex++) {
            Row row = this.getRow(rowIndex);
            Map> readCellDataMap = this.readRow(row);
            T resultData = getObjectResult(readCellDataMap);
            resultDataList.add(resultData);
        }

        return resultDataList;
    }

    private T getObjectResult(Map> readCellDataMap) {
        if (Map.class.isAssignableFrom(this.sheetReaderConfigMainDefinition.getClazz())) {
            //noinspection unchecked
            return parseToMap((SheetReaderConfigMainDefinition>) sheetReaderConfigMainDefinition, readCellDataMap);
        } else {
            return parseToObject(sheetReaderConfigMainDefinition, readCellDataMap);
        }
    }

    private Map> getSortHeadReadCellDataMap() {
        if (sortHeadReadCellDataMap == null) {
            this.readHead();
        }
        return sortHeadReadCellDataMap;
    }

    private Map> getTitleHeadReadCellDataMap() {
        if (this.titleHeadReadCellDataMap != null) {
            return this.titleHeadReadCellDataMap;
        }

        Map> sortHeadReadCellDataMap = this.getSortHeadReadCellDataMap();
        Map> titleHeadReadCellDataMap = new HashMap<>(sortHeadReadCellDataMap.size());
        for (Map.Entry> entry : sortHeadReadCellDataMap.entrySet()) {
            ReadCellData headReadCellData = entry.getValue();

            String headValue;
            if (headReadCellData.getType().equals(CellDataTypeEnum.EMPTY)) {
                headValue = "";
            } else {
                ReadConverter headReadConverter = this.getReadConverter(Object.class, headReadCellData.getType());
                headValue = String.valueOf(headReadConverter.convertToJavaData(headReadCellData));
            }
            titleHeadReadCellDataMap.put(headValue, headReadCellData);
        }

        this.titleHeadReadCellDataMap = titleHeadReadCellDataMap;
        return this.titleHeadReadCellDataMap;
    }

    private Row getRow(int rowIndex) {
        return this.sheet.getRow(rowIndex);
    }

    private Map> readRow(Row row) {
        short lastCellNum = row.getLastCellNum();
        Map> readCellDataMap = new HashMap<>(Math.max(16, lastCellNum));
        for (int columnIndex = dataColumnStartIndex; columnIndex < lastCellNum; columnIndex++) {
            Cell cell = row.getCell(columnIndex);
            ReadCellData readCellData = cellReader.readCellData(cell);
            readCellDataMap.put(columnIndex, readCellData);
        }

        return readCellDataMap;
    }

    private T parseToMap(SheetReaderConfigMainDefinition> mainDefinition, Map> readCellDataMap) {
        //noinspection unchecked
        Map result = (Map) mainDefinition.getClazzInstance();
        Map> headReadCellDataMap = this.getSortHeadReadCellDataMap();
        for (Map.Entry> entry : readCellDataMap.entrySet()) {
            Integer key = entry.getKey();
            ReadCellData readCellData = entry.getValue();
            Object value;
            if (readCellData.getType().equals(CellDataTypeEnum.EMPTY)) {
                value = null;
            } else {
                CellDataTypeEnum excelType = readCellData.getType();
                ReadConverter readConverter = this.getReadConverter(Object.class, excelType);
                value = readConverter.convertToJavaData(readCellData);
            }

            Object headValue;
            ReadCellData headReadCellData = headReadCellDataMap.get(key);
            if (headReadCellData.getType().equals(CellDataTypeEnum.EMPTY)) {
                headValue = "";
            } else {
                ReadConverter headReadConverter = this.getReadConverter(Object.class, headReadCellData.getType());
                headValue = headReadConverter.convertToJavaData(headReadCellData);
            }

            result.put(headValue, value);
        }
        //noinspection unchecked
        return (T) result;
    }

    private T parseToObject(SheetReaderConfigMainDefinition mainDefinition, Map> readCellDataMap) {
        SheetHeadModel sheetHeadModel = mainDefinition.getSheetHeadModel();
        if (sheetHeadModel == null || SheetHeadModel.sort.equals(sheetHeadModel)) {
            return parseToObjectBySortModel(mainDefinition, readCellDataMap);
        } else {
            return parseToObjectByTitleModel(sheetReaderConfigMainDefinition, readCellDataMap);
        }

    }

    private T parseToObjectByTitleModel(SheetReaderConfigMainDefinition mainDefinition, Map> readCellDataMap) {
        Map> titleHeadReadCellDataMap = this.getTitleHeadReadCellDataMap();

        T result = mainDefinition.getClazzInstance();
        List itemDefinitionList = mainDefinition.getItemDefinitionList();

        for (SheetReaderConfigItemDefinition itemDefinition : itemDefinitionList) {
            String title = itemDefinition.getTitle();
            ReadCellData titleHeadReadCellData = titleHeadReadCellDataMap.get(title);
            if (titleHeadReadCellData == null) {
                continue;
            }
            Integer columnIndex = titleHeadReadCellData.getColumnIndex();
            ReadCellData readCellData = readCellDataMap.get(columnIndex);
            this.invokeValue(result, itemDefinition, readCellData);
        }
        return result;

    }

    private T parseToObjectBySortModel(SheetReaderConfigMainDefinition mainDefinition, Map> readCellDataMap) {
        T result = mainDefinition.getClazzInstance();
        List itemDefinitionList = mainDefinition.getItemDefinitionList();

        int dataColumnStartIndex = this.getDataColumnStartIndex();
        for (int i = 0; i < itemDefinitionList.size(); i++) {
            SheetReaderConfigItemDefinition itemDefinition = itemDefinitionList.get(i);
            // 数据实际所在了列
            int realColumnIndex = i + dataColumnStartIndex;
            ReadCellData readCellData = readCellDataMap.get(realColumnIndex);
            this.invokeValue(result, itemDefinition, readCellData);
        }
        return result;
    }

    /**
     * 设置值
     */
    private void invokeValue(T result, SheetReaderConfigItemDefinition itemDefinition, ReadCellData readCellData) {
        Object value;
        if (readCellData.getType().equals(CellDataTypeEnum.EMPTY)) {
            value = null;
        } else {
            ReadConverter readConverter;
            Class> readConverterClazz = itemDefinition.getReadConverterClazz();
            if (readConverterClazz != null && !readConverterClazz.equals(NoneReadConverter.class)) {
                readConverter = this.getReadConverter(readConverterClazz);
            } else {
                Class javaType = itemDefinition.getFieldType();
                CellDataTypeEnum excelType = readCellData.getType();
                readConverter = this.getReadConverter(javaType, excelType);
            }
            value = readConverter.convertToJavaData(readCellData);
        }

        String fieldName = itemDefinition.getFieldName();
        CommonUtils.invokeSetter(result, fieldName, value);
    }

    private ReadConverter getReadConverter(Class javaType, CellDataTypeEnum excelType) {
        ReadConverter readConverter = readConverterMap.get(ConverterKeyBuild.buildKey(javaType, excelType));
        if (readConverter == null) {
            throw new ExcelException(String.format("%s,%s无对应的转换器", javaType, excelType));
        }
        return readConverter;
    }

    private ReadConverter getReadConverter(Class> readConvertClazz) {
        ReadConverter readConverter = this.getReadConverterClazzMap().get(readConvertClazz);
        if (readConverter == null) {
            throw new ExcelException(String.format("%s无对应的转换器", readConvertClazz));
        }
        return readConverter;
    }

    private Map, ReadConverter> getReadConverterClazzMap() {
        if (readConverterClazzMap == null) {
            readConverterClazzMap = new HashMap<>(this.readConverterMap.size());
            this.readConverterMap.values().forEach(readConverter -> readConverterClazzMap.put(readConverter.getClass(), readConverter));
        }
        return readConverterClazzMap;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy