Java excel poi/easyexcel读取合并单元格内容


import cn.com.rydeen.base.utils.data.JsonUtils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * author:yh
 */
@Slf4j
public class ExcelUtils {
    /**
     * 普通的读取Excel数据
     * @param inputStream
     * @param sheetNo
     * @param headRowNumber
     * @param clazz
     * @return
     * @param <T>
     */
    public static <T> List<T> readExcelData(ByteArrayInputStream inputStream, int sheetNo, int headRowNumber, Class<T> clazz) {
        List<T> dataList = new ArrayList<>();

        EasyExcel.read(inputStream, clazz, new AnalysisEventListener<T>() {
                    @Override
                    public void invoke(T data, AnalysisContext context) {
                        dataList.add(data);
                    }

                    @Override
                    public void doAfterAllAnalysed(AnalysisContext context) {
                        log.info("doAfterAllAnalysed done");
                    }
                }).sheet(sheetNo)
                .headRowNumber(headRowNumber)
                .doRead();

        log.info("dataList: {}", JsonUtils.getInstance().serialize(dataList));
        return dataList;
    }
    /**
     * 读取Excel数据,适配excel存在列数据合并的,以及过滤中间行为空的数据
     * @param inputStream
     * @param sheetNo
     * @param headRowNumber
     * @param clazz
     * @return
     * @param <T>
     */
    public static <T> List<T> readExcelDataWithOutEmptyLine(ByteArrayInputStream inputStream, int sheetNo, int headRowNumber, Class<T> clazz) throws IOException {
        List<T> dataList = new ArrayList<>();
        Workbook workbook = new XSSFWorkbook(inputStream);
        Sheet sheet = workbook.getSheetAt(sheetNo);

        // 获取字段和列的映射关系
        Field[] fields = clazz.getDeclaredFields();

        // 读取每一行数据
        for (int i = headRowNumber; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row == null || isRowEmpty(row)) {
                // 跳过空行
                continue;
            }

            try {
                T instance = clazz.getDeclaredConstructor().newInstance();
                for (Field field : fields) {
                    field.setAccessible(true);
                    //结合easyexcel注解获取列索引和字段名
                    ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
                    if (excelProperty != null) {
                        int columnIndex = excelProperty.index();
                        Cell cell = row.getCell(columnIndex);
                        if (cell == null || cell.getCellType() == CellType.BLANK) {
                            // 获取合并单元格的值
                            cell = getMergedRegionValue(row.getRowNum(), columnIndex, sheet);
                        }
                        setFieldValue(instance, field, cell);
                    }
                }
                dataList.add(instance);
            } catch (Exception e) {
                e.printStackTrace();
                // 处理反射异常或转换错误
            }
        }

        workbook.close();
        return dataList;
    }

    private static boolean isRowEmpty(Row row) {
        for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {
            Cell cell = row.getCell(i);
            if (cell != null && cell.getCellType() != CellType.BLANK) {
                return false;
            }
        }
        return true;
    }

    private static Cell getMergedRegionValue(int row, int column, Sheet sheet) {
        for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
            CellRangeAddress range = sheet.getMergedRegion(i);
            if (range.isInRange(row, column)) {
                Row firstRow = sheet.getRow(range.getFirstRow());
                return firstRow.getCell(range.getFirstColumn());
            }
        }
        return null;
    }


    private static void setFieldValue(Object instance, Field field, Cell cell) throws IllegalAccessException {
        if (cell != null) {
            // 使用DecimalFormat将数字转换为字符串,避免科学计数法 TODO 优化
            DecimalFormat df = new DecimalFormat("#.##########");
            switch (cell.getCellType()) {
                case STRING:
                    field.set(instance, cell.getStringCellValue());
                    break;
                case NUMERIC:

                    String numericValue = df.format(cell.getNumericCellValue());
                    field.set(instance, numericValue);
                    break;
                case BOOLEAN:
                    field.set(instance, String.valueOf(cell.getBooleanCellValue()));
                    break;
                case FORMULA:
                    // 如果公式计算结果为数值,仍然按数值格式化为字符串
                    switch (cell.getCachedFormulaResultType()) {
                        case NUMERIC:
                            String formulaNumericValue = df.format(cell.getNumericCellValue());
                            field.set(instance, formulaNumericValue);
                            break;
                        case STRING:
                            field.set(instance, cell.getStringCellValue());
                            break;
                        default:
                            break;
                    }
                    break;
                default:
                    break;
            }
        }
    }

}

  1. readExcelData 方法
    功能: 读取 Excel 文件中的数据,返回一个列表。
    参数:
    inputStream: 输入流,通常用于从内存中读取数据。
    sheetNo: 要读取的工作表编号。
    headRowNumber: 表头所在的行号。
    clazz: 泛型参数,代表实体类的类型。
    返回值: 包含读取数据的列表。
    实现:
    使用 EasyExcel 的 read 方法读取数据。
    通过 AnalysisEventListener 监听器收集每行数据。
    将数据添加到列表中并返回。
  2. readExcelDataWithOutEmptyLine 方法
    功能: 读取 Excel 文件中的数据,处理合并单元格,并过滤掉所有列为空的行。
    参数:
    同 readExcelData 方法。
    返回值: 包含读取数据的列表。
    实现:
    打开 Excel 文件并获取指定工作表。
    遍历每一行数据。
    跳过所有列为空的行。
    对于每个非空行,创建实体类实例,并设置属性值。
    设置属性值时考虑合并单元格的情况。
    将有效数据添加到列表中并返回。
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值