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

com.thomas.alib.excel.importer.ExcelImportSheetItem Maven / Gradle / Ivy

package com.thomas.alib.excel.importer;

import com.thomas.alib.excel.base.ExcelColumnRender;
import com.thomas.alib.excel.exception.AnalysisException;
import com.thomas.alib.excel.importer.validation.ImportValidator;
import com.thomas.alib.excel.importer.validation.ImportValidatorFactory;
import com.thomas.alib.excel.utils.CollectionUtils;
import com.thomas.alib.excel.utils.ReflectUtil;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;

/**
 * Excel导入时处理每个工作表(Sheet)的解析工具
 *
 * @param  数据源对象类型泛型
 */
class ExcelImportSheetItem implements AutoCloseable {
    private static final Logger logger = LoggerFactory.getLogger(ExcelImportSheetItem.class);
    /**
     * excel工作簿对象
     */
    Workbook mWorkbook;
    /**
     * excel公式转换器
     */
    FormulaEvaluator formulaEvaluator;
    /**
     * 本次处理的sheet对象
     */
    Sheet mSheet;
    /**
     * 本次读取对应数据类的泛型
     */
    Class dataClazz;
    /**
     * 根据sheet表格的表头解析的数据列Map
     */
    HashMap columnFieldItemMap;
    /**
     * 本次处理的sheet所包含的总行数(包括所谓的表头行)
     */
    int lineCount;
    /**
     * 导入时数据验证器
     */
    ImportValidator importValidator;

    ExcelImportSheetItem(Workbook workbook, Sheet sheet, Class clazz) {
        this.mWorkbook = workbook;
        this.formulaEvaluator = this.mWorkbook.getCreationHelper().createFormulaEvaluator();
        this.mSheet = sheet;
        this.dataClazz = clazz;
        this.columnFieldItemMap = new HashMap<>();
        this.lineCount = this.mSheet.getLastRowNum() - this.mSheet.getFirstRowNum();
        this.importValidator = ImportValidatorFactory.build();
    }

    /**
     * 读取sheet中的数据列表
     *
     * @return 数据列表
     */
    List readList() {
        List result = new ArrayList<>();
        int first_row = mSheet.getFirstRowNum(), last_row = mSheet.getLastRowNum();
        if (first_row == last_row) return result;//空sheet
        readHeadRow(mSheet.getRow(first_row++));
        for (int row_index = first_row; row_index <= last_row; ++row_index) {//遍历行
            Row row = mSheet.getRow(row_index);
            if (row == null) continue;//getRow是空说明这一行没有任何编辑项,没有被修改过。跳过
            T t;
            try {
                t = dataClazz.newInstance();
                boolean allValueIsNull = true;
                for (ExcelImportColumnItem column : columnFieldItemMap.values()) {
                    if (column.getColumnIndex() < 0) continue;
                    try {
                        Cell cell = row.getCell(column.getColumnIndex());
                        Object value = column.setColumnValueFromCell(t, cell, formulaEvaluator);
                        if (value != null) allValueIsNull = false;
                    } catch (Throwable e) {
                        throw new RuntimeException("表格\"" + column.getHeadName() + "\"列-第" + row_index + "行-解析时发生错误:", e);
                    }
                }
                if (allValueIsNull) {
                    continue;//解析所有字段都是空,这行数据跳过
                }
            } catch (Throwable e) {
                throw new RuntimeException("表格第" + row_index + "行-解析时发生错误:", e);
            }
            //验证器存在才进行验证判断
            if (importValidator != null) {
                Set validateSet = importValidator.validate(t);
                if (!CollectionUtils.isEmpty(validateSet)) {
                    throw new RuntimeException("表格第" + row_index + "行:" + validateSet.iterator().next());
                }
            }
            result.add(t);
        }
        return result;
    }

    /**
     * 读取sheet中的数据列表,安全模式,会把整个文件读完,并把错误信息返回而不是抛出异常
     *
     * @param consumer 读取一条的回调
     * @return 数据列表
     */
    List> readListSafety(Consumer> consumer) {
        List> result = new ArrayList<>();
        int first_row = mSheet.getFirstRowNum(), last_row = mSheet.getLastRowNum();
        if (first_row == last_row) return result;//空sheet
        readHeadRow(mSheet.getRow(first_row++));
        for (int row_index = first_row; row_index <= last_row; ++row_index) {//遍历行
            Row row = mSheet.getRow(row_index);
            if (row == null) continue;//getRow是空说明这一行没有任何编辑项,没有被修改过。跳过
            SafetyResult safety = new SafetyResult<>(row_index);
            T t;
            try {
                t = dataClazz.newInstance();
                boolean allValueIsNull = true;
                for (ExcelImportColumnItem column : columnFieldItemMap.values()) {
                    if (column.getColumnIndex() < 0) continue;
                    try {
                        Cell cell = row.getCell(column.getColumnIndex());
                        Object value = column.setColumnValueFromCell(t, cell, formulaEvaluator);
                        if (value != null) allValueIsNull = false;
                    } catch (Throwable e) {
                        String e_label = "表格\"" + column.getHeadName() + "\"列-第" + row_index + "行-解析时发生错误:";
                        logger.error(e_label, e);
                        safety.setReadSuccess(false);
                        if (e instanceof AnalysisException) {
                            safety.appendMsg(e_label + e.getLocalizedMessage() + ";");
                        } else {
                            safety.appendMsg(e_label + "未知错误,请联系管理员;");
                        }
                    }
                }
                if (allValueIsNull) {
                    continue;//解析所有字段都是空,这行数据跳过
                }
            } catch (Throwable e) {
                String e_label = "表格第" + row_index + "行-解析时发生错误:";
                logger.error(e_label, e);
                t = null;
                safety.setReadSuccess(false);
                safety.appendMsg(e_label + "未知错误,请联系管理员;");
            }
            safety.setData(t);
            //验证对象不为空,且验证器存在才进行验证判断
            if (t != null && importValidator != null) {
                Set validateSet = importValidator.validate(t);
                if (!CollectionUtils.isEmpty(validateSet)) {
                    safety.setReadSuccess(false);
                    if (safety.getMsg().isEmpty()) {
                        safety.appendMsg("表格第" + row_index + "行:");
                    }
                    for (String validateMsg : validateSet) {
                        safety.appendMsg(validateMsg + ";");
                    }
                }
            }
            if (consumer != null) {
                try {
                    consumer.accept(safety);
                } catch (Throwable e) {
                    logger.error("表格第" + row_index + "行-回调时发生错误:", e);
                }
            }
            result.add(safety);
        }
        return result;
    }

    /**
     * 读取表头行(第一行)
     *
     * @param row 表头行
     */
    private void readHeadRow(Row row) {
        //全部的成员列表
        List total_field_list = ReflectUtil.getAccessibleFieldIncludeSuper(dataClazz);
        //遍历寻找所有有效column成员
        for (Field item_field : total_field_list) {
            ExcelImportColumnItem column = new ExcelImportColumnItem(item_field);
            if (column.isValid() && !column.isPicture()) {//有效且不按图片处理
                columnFieldItemMap.put(column.getHeadName(), column);
            }
        }
        int first_cell = row.getFirstCellNum(), last_cell = row.getLastCellNum();
        for (int cell_index = first_cell; cell_index < last_cell; ++cell_index) {//遍历表头行
            Cell cell = row.getCell(cell_index);
            ExcelImportColumnItem column = columnFieldItemMap.get(readHeadCell(cell));
            if (column != null) {
                column.setColumnIndex(cell_index);
            }
        }
    }

    /**
     * 读取表头项的值
     *
     * @param cell 表头项
     * @return 表头项的值
     */
    private String readHeadCell(Cell cell) {
        String column = "";
        CellType cellType = cell.getCellType();
        switch (cellType) {
            case NUMERIC:
                column = String.valueOf(cell.getDateCellValue());
                break;
            case STRING:
                column = cell.getStringCellValue();
                break;
            case FORMULA:
                column = cell.getCellFormula();
                break;
            case BOOLEAN:
                column = String.valueOf(cell.getBooleanCellValue());
                break;
            case ERROR:
            case BLANK:
                column = " ";
                break;
        }
        return column;
    }

    /**
     * 关闭,目前仅用于关闭验证器工厂
     */
    @Override
    public void close() {
        mWorkbook = null;
        formulaEvaluator = null;
        mSheet = null;
        dataClazz = null;
        if (columnFieldItemMap != null) {
            columnFieldItemMap.values().forEach(ExcelColumnRender::close);
            columnFieldItemMap.clear();
        }
        columnFieldItemMap = null;
        lineCount = 0;
        //如果验证器存在,关闭他
        if (importValidator != null) {
            try {
                importValidator.close();
            } catch (Throwable e) {
                logger.error("验证器工厂关闭时发生错误:", e);
            }
            importValidator = null;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy