EasyExcel解析合并单元格@ExcelProperty

根据名称解析-value

本质上来说,根据名称解析也是获取到名称对应的下标/索引进行解析,如果是根据索引进行解析,不需要名称对应转换步骤即可
使用方式为:new ExcelAnalysisHelper().getList(file, T.class);
@ExcelProperty(value = “序号”,index = 1),其中value为名称,index为索引
根据索引解析可参考(我也是参考别人的文档):根据索引解析

ExcelAnalysisHelper

package com.meiyuan.controller.excel;

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.meiyuan.commons.tools.exception.ErrorCode;
import com.meiyuan.order.exception.OrdersException;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

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

/**
 * * 模板的读取类
 *
 * @author syx
 * @version 1.0.0
 * @date 2020/12/21 9:44
 */
@Slf4j
public class ExcelAnalysisHelper<T> {

    public List<T> getList(MultipartFile file, Class<T> clazz) {
        return getList(file, clazz, 0, 1);
    }

    public List<T> getList(MultipartFile file, Class<T> clazz, Integer sheetNo, Integer headRowNumber) {
        UploadDataListener<T> listener = new UploadDataListener<>(headRowNumber);
        try {
            EasyExcel.read(file.getInputStream(), clazz, listener).extraRead(CellExtraTypeEnum.MERGE).sheet(sheetNo).headRowNumber(headRowNumber).doRead();
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        List<CellExtra> extraMergeInfoList = listener.getExtraMergeInfoList();
        if (CollectionUtils.isEmpty(extraMergeInfoList)) {
            return listener.getData();
        }
        List<T> data = explainMergeData(listener.getData(), extraMergeInfoList, headRowNumber, file);
        return data;
    }

    /**
     * 处理合并单元格
     *
     * @param data               解析数据
     * @param extraMergeInfoList 合并单元格信息
     * @param headRowNumber      起始行
     * @return 填充好的解析数据
     */
    private List<T> explainMergeData(List<T> data, List<CellExtra> extraMergeInfoList, Integer headRowNumber, MultipartFile file) {
        XSSFWorkbook xssfWorkbook = null;
        try {
            xssfWorkbook = new XSSFWorkbook(file.getInputStream());
            XSSFSheet sheetAt = xssfWorkbook.getSheetAt(0);
            XSSFRow row = sheetAt.getRow(headRowNumber - 1);
            List<String> columnNames = new ArrayList<>();
            for (int rowNum = 0; rowNum <= row.getLastCellNum() - 1; rowNum++) {
                columnNames.add(row.getCell(rowNum).getStringCellValue());
            }
//        循环所有合并单元格信息
            extraMergeInfoList.forEach(cellExtra -> {
                int firstRowIndex = cellExtra.getFirstRowIndex() - headRowNumber;
                int lastRowIndex = cellExtra.getLastRowIndex() - headRowNumber;
                int firstColumnIndex = cellExtra.getFirstColumnIndex();
                int lastColumnIndex = cellExtra.getLastColumnIndex();
//            获取初始值
                if (firstRowIndex < data.size()) {
                    Object initValue = getInitValueFromList(firstRowIndex, firstColumnIndex, data, columnNames);
//            设置值
                    for (int i = firstRowIndex; i <= lastRowIndex; i++) {
                        for (int j = firstColumnIndex; j <= lastColumnIndex; j++) {
                            setInitValueToList(initValue, i, j, data, columnNames);
                        }
                    }
                }
            });
        } catch (IOException e) {
            log.error("文件【{}】解析失败【{}】", file, e);
        }
        return data;
    }

    /**
     * 设置合并单元格的值
     *
     * @param filedValue  值
     * @param rowIndex    行
     * @param columnIndex 列
     * @param data        解析数据
     */
    public void setInitValueToList(Object filedValue, Integer rowIndex, Integer columnIndex, List<T> data, List<String> columnNames) {
        T object = data.get(rowIndex);

        for (Field field : object.getClass().getDeclaredFields()) {
            //提升反射性能,关闭安全检查
            field.setAccessible(true);
            ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
            if (annotation != null) {
                String names = "";
                for (String s : annotation.value()) {
                    names = names + s;
                }
                int index = columnNames.indexOf(names);
                if (index == columnIndex) {
                    try {
                        field.set(object, filedValue);
                        break;
                    } catch (IllegalAccessException e) {
                        throw new OrdersException(ErrorCode.INTERNAL_SERVER_ERROR, "解析数据时发生异常!");
                    }
                }
            }
        }
    }


    /**
     * 获取合并单元格的初始值
     * rowIndex对应list的索引
     * columnIndex对应实体内的字段
     *
     * @param firstRowIndex    起始行
     * @param firstColumnIndex 起始列
     * @param data             列数据
     * @param nameList         excel表头名称
     * @return 初始值
     */
    private Object getInitValueFromList(Integer firstRowIndex, Integer firstColumnIndex, List<T> data, List<String> nameList) {
        Object filedValue = null;
        T object = data.get(firstRowIndex);
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            //提升反射性能,关闭安全检查
            field.setAccessible(true);
            ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
            if (annotation != null) {
                String names = "";
                for (String s : annotation.value()) {
                    names = names + s;
                }
                int index = nameList.indexOf(names);
                if (index == firstColumnIndex) {
                    try {
                        filedValue = field.get(object);
                        break;
                    } catch (IllegalAccessException e) {
                        throw new OrdersException(ErrorCode.INTERNAL_SERVER_ERROR, "解析数据时发生异常!");
                    }
                }
            }
        }
        return filedValue;
    }

    /**
     * 将EXCEL中A,B,C,D,E列映射成0,1,2,3
     *
     * @param col
     */
    private int getExcelCol(String col) {
        col = col.toUpperCase();
        // 从-1开始计算,字母重1开始运算。这种总数下来算数正好相同。
        int count = -1;
        char[] cs = col.toCharArray();
        for (int i = 0; i < cs.length; i++) {
            count += (cs[i] - 64) * Math.pow(26, cs.length - 1 - i);
        }
        return count;
    }
}

UploadDataListener

package com.meiyuan.controller.excel;

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 lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * * 模板的读取类
 *
 * @author syx
 * @version 1.0.0
 * @date 2020/12/21 9:44
 */
@Slf4j
public class UploadDataListener<T> extends AnalysisEventListener<T> {

    /**
     * 解析的数据
     */
    List<T> list = new ArrayList<>();

    /**
     * 正文起始行
     */
    private Integer headRowNumber;
    /**
     * 合并单元格
     */
    private List<CellExtra> extraMergeInfoList = new ArrayList<>();

    public UploadDataListener(Integer headRowNumber) {
        this.headRowNumber = headRowNumber;
    }

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context context
     */
    @Override
    public void invoke(T data, AnalysisContext context) {
        list.add(data);
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    public List<T> getData() {
        return list;
    }

    @Override
    public void extra(CellExtra extra, AnalysisContext context) {
        if (extra.getType() == CellExtraTypeEnum.MERGE) {
            if (extra.getRowIndex() >= headRowNumber) {
                extraMergeInfoList.add(extra);
            }
        }
    }

    public List<CellExtra> getExtraMergeInfoList() {
        return extraMergeInfoList;
    }
}


你可能感兴趣的:(excel,java,poi)