若依导出excel,合并单元格

需求描述 :表格中订单对应的商品和运单为list,且商品和运单数量不一致,展示时候以多的条目为行数,少的展示空行。具体如下图所示

若依中整合POI的工具类无法满足如下需求

Snipaste_2023-11-21_16-52-40

在自定义注解 Excel 中添加字段

    /**
     * 是否需要合并行  与 needMerge 以及 子列表不兼容
     */
    public boolean lineMerge() default false;

    /**
     * 合并行的依据的主键
     */
    public boolean lineMergeId() default false;

修改 ExcelUtil.fillExcelData方法

    public void fillExcelData(int index, Row row) {
        int startNo = index * sheetSize;
        int endNo = Math.min(startNo + sheetSize, list.size());
        int rowNo = (1 + rownum) - startNo;
        String objIdValve = "";//注解中 lineMergeId 为true的value 合并单元格使用
        int mergeStartRow = 0;//合并单元格 起始行

        for (int i = startNo; i < endNo; i++) {
            rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo;
            row = sheet.createRow(rowNo);
            // 得到导出对象.
            T vo = (T) list.get(i);
            Collection<?> subList = null;
            if (isSubList()) {
                if (isSubListValue(vo)) {
                    subList = getListCellValue(vo);
                    subMergedLastRowNum = subMergedLastRowNum + subList.size();
                } else {
                    subMergedFirstRowNum++;
                    subMergedLastRowNum++;
                }
            }
            int column = 0;
            boolean mergeCells = false;//合并单元格 当前单元格是否需要合并
            for (Object[] os : fields) {
                Field field = (Field) os[0];
                Excel excel = (Excel) os[1];

                /**
                 * 合并单元格判断条件处理
                 */
                if (excel.lineMergeId()) {
                    try {
                        Object value = getTargetValue(vo, field, excel);
                        if (!objIdValve.equals(value.toString())) {
                            objIdValve = value.toString();
                            mergeCells = false;
                            mergeStartRow = rowNo;
                        } else {
                            mergeCells = true;
                        }
                    } catch (Exception e) {
                        log.error("合并单元格导出主键获取失败,导出Excel失败{}", e);
                    }
                }

                if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList)) {
                    boolean subFirst = false;
                    for (Object obj : subList) {
                        if (subFirst) {
                            rowNo++;
                            row = sheet.createRow(rowNo);
                        }
                        List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class);
                        int subIndex = 0;
                        for (Field subField : subFields) {
                            if (subField.isAnnotationPresent(Excel.class)) {
                                subField.setAccessible(true);
                                Excel attr = subField.getAnnotation(Excel.class);
                                this.addCell(attr, row, (T) obj, subField, column + subIndex);
                            }
                            subIndex++;
                        }
                        subFirst = true;
                    }
                    this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size();
                } else {
                    this.addCell(excel, row, vo, field, column++);
                }

                /**
                 * 合并单元格操作
                 */
                if (excel.lineMerge() && mergeCells) {
                    if (rowNo - mergeStartRow > 1) {
                        List<CellRangeAddress> cellList = new ArrayList<>(sheet.getMergedRegions());
                        for (int i1 = 0; i1 < cellList.size(); i1++) {
                            CellRangeAddress ca = cellList.get(i1);
                            if (mergeStartRow == ca.getFirstRow() && rowNo - 1 == ca.getLastRow() && column - 1 == ca.getFirstColumn() && column - 1 == ca.getLastColumn()) {
                                sheet.removeMergedRegion(i1);
                            }
                        }
                    }
                    sheet.addMergedRegion(new CellRangeAddress(mergeStartRow, rowNo, column - 1, column - 1));
                }
            }
        }
    }

具体使用方式

​ 在订单编号 @Excel注解中添加 lineMergeId = true,合并单元格的行以此为合并依据,没有此标记则不会执行合并单元格

​ 在需要合并的列中的@Excel注解中添加 lineMerge = true

注:自定义注解 Excel中原有 needMerge字段 以及 ExcelUtil中的子列表不兼容

import com.ruoyi.common.core.annotation.Excel;
import lombok.Data;

import java.math.BigDecimal;
import java.time.LocalDateTime;

@Data
public class Test {

    @Excel(name = "订单编号", lineMerge = true, lineMergeId = true)
    private String orderNo;

    @Excel(name = "订单名称", lineMerge = true)
    private String orderName;

    @Excel(name = "总价", lineMerge = true)
    private BigDecimal amount;

    @Excel(name = "商品名称")
    private String goodsName;

    @Excel(name = "单价")
    private BigDecimal price;

    @Excel(name = "数量")
    private Double quantity;

    @Excel(name = "预计到达时间", lineMerge = true)
    private LocalDateTime arriveDate;

    @Excel(name = "快递公司")
    private String express;

    @Excel(name = "发货时间")
    private LocalDateTime deliveryDate;

    @Excel(name = "发货数量")
    private Double quantityShipped;

    @Excel(name = "到货时间")
    private Double trueArriveDate;

    @Excel(name = "税率", lineMerge = true)
    private Double taxRate;

    @Excel(name = "税额", lineMerge = true)
    private BigDecimal taxAmount;
    
    @Excel(name = "是否完成", lineMerge = true, readConverterExp = "0=否,1=是")
    private Integer completed;
    
}

posted @ 2023-11-22 08:54  qianyoo  阅读(2169)  评论(0编辑  收藏  举报