【学习总结】EasyExcel合并同列不同行,表格数据相同的行

实体类

java 复制代码
@Data
@HeadRowHeight(50)
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER, verticalAlignment = VerticalAlignmentEnum.CENTER, wrapped = BooleanEnum.TRUE)
public class CriterionDataExportDTO {


    @ColumnWidth(15)
    @ExcelProperty(value = "所属街道")
    private String streetName;

    @ColumnWidth(25)
    @ExcelProperty(value = "点位类型")
    private String pointType;

    @ColumnWidth(40)
    @ExcelProperty(value = "测评点位")
    private String pointName;

    @ColumnWidth(50)

    @ExcelProperty(value = "问题明细")
    private String issueDetails;

    @ColumnWidth(15)
    @ExcelProperty(value = "问题笔数")
    private Integer issueCount;

    @ColumnWidth(25)
    @ExcelProperty(value = "二级负责单位")
    private String responsibleUnit2;

    @ColumnWidth(25)
    @ExcelProperty(value = "二级单位接件时间")
    private String assignTime2;

    @ColumnWidth(25)
    @ExcelProperty(value = "三级负责单位")
    private String responsibleUnit3;

    @ColumnWidth(25)
    @ExcelProperty(value = "三级单位接件时间")
    private String assignTime3;

    @ExcelIgnore
    private Integer pushStatus;

}

工具类

继承合并单元格,重写合并方法

java 复制代码
package com.jeesite.modules.utils.easyExcel;

import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.*;

public class EasyExcelUtils extends AbstractMergeStrategy {
    private Map<String, List<Integer>> nameRowMap = new HashMap<>();

    @Override
    protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
        int columnIndex = cell.getColumnIndex();

        if (columnIndex == 0) {
            String currentValue = cell.getStringCellValue();
            if (currentValue == null || currentValue.isEmpty()) {
                return;
            }

            int currentRowIndex = cell.getRowIndex();
            List<Integer> rowList = nameRowMap.getOrDefault(currentValue, new ArrayList<>());
            rowList.add(currentRowIndex);
            nameRowMap.put(currentValue, rowList);

            mergeRows(sheet, currentValue, rowList, columnIndex);
        }

        if (columnIndex == 2) {
            String currentValue = cell.getStringCellValue();
            if (currentValue == null || currentValue.isEmpty()) {
                return;
            }

            int currentRowIndex = cell.getRowIndex();
            List<Integer> rowList = nameRowMap.getOrDefault(currentValue, new ArrayList<>());
            rowList.add(currentRowIndex);
            nameRowMap.put(currentValue, rowList);

            mergeRows(sheet, currentValue, rowList, columnIndex);
        }
    }

    private void mergeRows(Sheet sheet, String value, List<Integer> rowList, int columnIndex) {
        if (rowList.size() <= 1) {
            return;
        }

        int startRow = rowList.get(0);
        int endRow = rowList.get(rowList.size() - 1);

        // 检查是否存在重叠合并区域
        CellRangeAddress existingRegion = findOverlappingRegion(sheet, startRow, endRow, columnIndex);
        if (existingRegion != null) {
            // 扩展现有合并区域以适应新的合并行
            startRow = Math.min(existingRegion.getFirstRow(), startRow);
            endRow = Math.max(existingRegion.getLastRow(), endRow);

            // 移除现有合并区域
            removeMergedRegion(sheet, existingRegion);
        }

        CellRangeAddress range = new CellRangeAddress(startRow, endRow, columnIndex, columnIndex);
        sheet.addMergedRegionUnsafe(range);
    }

    private CellRangeAddress findOverlappingRegion(Sheet sheet, int startRow, int endRow, int columnIndex) {
        for (CellRangeAddress region : sheet.getMergedRegions()) {
            if (region.getFirstColumn() == columnIndex && region.getLastColumn() == columnIndex) {
                // 只考虑指定列的合并区域
                if (startRow <= region.getLastRow() && endRow >= region.getFirstRow()) {
                    return region;
                }
            }
        }
        return null;
    }

    private void removeMergedRegion(Sheet sheet, CellRangeAddress region) {
        int index = -1;
        for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
            CellRangeAddress mergedRegion = sheet.getMergedRegion(i);
            if (mergedRegion.equals(region)) {
                index = i;
                break;
            }
        }
        if (index >= 0) {
            sheet.removeMergedRegion(index);
        }
    }
}

调用

java 复制代码
public void exportTaskDetails() {
        List<CriterionDataExportDTO> dataDetails = dataDao.findTaskDataDetails();
        for (CriterionDataExportDTO item : dataDetails) {
            //数据处理
            }
        }
		
		//写入路径
        String fileName =  "D:\\数据测试_" + System.currentTimeMillis() + ".xlsx";
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);

        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short)15);
        headWriteCellStyle.setWriteFont(headWriteFont);

        HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
        EasyExcel.write(fileName, CriterionDataExportDTO.class)
                .registerWriteHandler(new EasyExcelUtils())
                .registerWriteHandler(horizontalCellStyleStrategy)
                .sheet("模板")
                .doWrite(dataDetails);

    }
    
    
    
相关推荐
BreezeJuvenile2 分钟前
外设模块学习(10)——红外避障模块(STM32)
stm32·单片机·学习·红外避障模块
Mos_x5 分钟前
HeidiSQL导入与导出数据
java·后端
codeyanwu5 分钟前
SQL 学习笔记
笔记·sql·学习
oak隔壁找我17 分钟前
Elasticsearch QueryBuilders 高级使用案例
java·后端
青云交20 分钟前
Java 大视界 -- Java 大数据在智能家居能源消耗模式分析与节能策略制定中的应用
java·大数据·智能家居·数据采集·能源消耗模式分析·节能策略制定·节能效果评估
Zhang青山22 分钟前
【玩转全栈】----Django基本配置和介绍
java·后端
71-324 分钟前
C语言——函数声明、定义、调用
c语言·笔记·学习·其他
民乐团扒谱机1 小时前
实验室安全教育与管理平台学习记录(四)机械建筑类安全
学习·安全
BUG?不,是彩蛋!1 小时前
Java Web 项目打包部署全解析:从 IDEA 配置到 Tomcat 运行
java·intellij-idea
JIngJaneIL1 小时前
财务管理|基于SprinBoot+vue的个人财务管理系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·毕设·财务管理系统