alibaba / easyexcel

快速、简洁、解决大文件内存溢出的java处理Excel工具
https://easyexcel.opensource.alibaba.com
Apache License 2.0
32.09k stars 7.5k forks source link

如何实现合并某列值相同的行 #3960

Open airufei opened 1 month ago

airufei commented 1 month ago

如何实现合并某列值相同的行,如下图所示: 需要把养护单位(maintenanceUnit)这列中值相同的行进行合并,并且行数不固定,如何实现? 企业微信截图_17248385989681

airufei commented 1 month ago

简单实现: public class RowSameValueMergeStrategy extends AbstractMergeStrategy {

/**
 * 需要合并的列位置索引
 */
private int[] mergeColumnIndexArray;

private Map<String, Integer> mergeMap = new HashMap<>();

public RowSameValueMergeStrategy(int[] mergeColumnIndexArray) {
    this.mergeColumnIndexArray = mergeColumnIndexArray;
}

@Override
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
    if (head == null) {
        return;
    }
    if (mergeColumnIndexArray == null) {
        return;
    }
    for (int i = 0; i < mergeColumnIndexArray.length; i++) {
        int mergeIndex = mergeColumnIndexArray[i];
        if (head.getColumnIndex() == mergeIndex) {
            String value = cell.getStringCellValue();
            int rowIndex = cell.getRowIndex();
            Integer lastRowIndex = mergeMap.get(value);
            if (lastRowIndex == null) {
                mergeMap.put(value, rowIndex);
            } else {
                // 合并单元格
                if (rowIndex > lastRowIndex) {
                    sheet.addMergedRegionUnsafe(new CellRangeAddress(
                            lastRowIndex, // 起始行
                            rowIndex,     // 结束行
                            mergeIndex,   // 起始列
                            mergeIndex   // 结束列
                    ));
                }

            }
        }
    }
}

}

g3230863 commented 1 month ago

public class CellMergeStrategy implements RowWriteHandler {

private final int mergeColumnIndex;

public CellMergeStrategy(int mergeColumnIndex) {
    this.mergeColumnIndex = mergeColumnIndex;
}

@Override
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
                            Integer relativeRowIndex, Boolean isHead) {
    if (isHead) {
        return;
    }
    Sheet sheet = writeSheetHolder.getSheet();
    SXSSFRow sr = (SXSSFRow) row;

    //行号
    int rowIndex = sr.getRowNum();

    String currentData = sr.getCell(mergeColumnIndex).getStringCellValue();
    String previousData = sheet.getRow(rowIndex - 1).getCell(mergeColumnIndex).getStringCellValue();

    // 如果当前单元格数据与上一个单元格数据相同,则合并
    if (currentData.equals(previousData)) {
        CellRangeAddress cellRangeAddress;
        cellRangeAddress = new CellRangeAddress(
                rowIndex - 1, rowIndex ,
                mergeColumnIndex, mergeColumnIndex
        );
        sheet.addMergedRegionUnsafe(cellRangeAddress);
    }

}

}

airufei commented 1 month ago

public class CellMergeStrategy implements RowWriteHandler {

private final int mergeColumnIndex;

public CellMergeStrategy(int mergeColumnIndex) {
    this.mergeColumnIndex = mergeColumnIndex;
}

@Override
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
                            Integer relativeRowIndex, Boolean isHead) {
    if (isHead) {
        return;
    }
    Sheet sheet = writeSheetHolder.getSheet();
    SXSSFRow sr = (SXSSFRow) row;

    //行号
    int rowIndex = sr.getRowNum();

    String currentData = sr.getCell(mergeColumnIndex).getStringCellValue();
    String previousData = sheet.getRow(rowIndex - 1).getCell(mergeColumnIndex).getStringCellValue();

    // 如果当前单元格数据与上一个单元格数据相同,则合并
    if (currentData.equals(previousData)) {
        CellRangeAddress cellRangeAddress;
        cellRangeAddress = new CellRangeAddress(
                rowIndex - 1, rowIndex ,
                mergeColumnIndex, mergeColumnIndex
        );
        sheet.addMergedRegionUnsafe(cellRangeAddress);
    }

}

}

大佬,有没有导出多个sheet,每个sheet的表头和数据不一样的代码示例(第一个sheet写ID、姓名、性别等;第二sheet 写订单编号、订单金额等)

LSL1618 commented 1 month ago

@airufei 多看文档 写入到单个或者多个Sheet