如何使用docx4j确定Excel工作表合并单元格范围并处理分组行?
处理Excel合并单元格分组并批量处理行集合
看起来你正在用Apache POI处理带合并单元格的Excel,需要把每个合并单元格对应的行打包成独立集合(比如set1、set2这类)分别处理对吧?结合你给出的代码片段,我整理了一个完整的实现思路和代码示例,帮你搞定这个需求:
1. 先梳理合并单元格的区域映射
首先得把所有合并单元格的覆盖范围整理清楚,这样后续能快速判断某一行属于哪个分组。用你已经拿到的CTMergeCells和SheetData,可以这么做:
// 构建映射:key是合并单元格的起始行号,value是该合并区域覆盖的所有行号集合 Map<Integer, Set<Integer>> mergeGroupMap = new HashMap<>(); if (mergeCells != null && mergeCells.getMergeCellList() != null) { for (CTMergeCell mergeCell : mergeCells.getMergeCellList()) { String ref = mergeCell.getRef(); // 解析合并区域(比如"A1:A5"格式) String[] refParts = ref.split(":"); CellAddress startAddr = new CellAddress(refParts[0]); CellAddress endAddr = new CellAddress(refParts[1]); int startRow = startAddr.getRow(); Set<Integer> coveredRows = new HashSet<>(); // 把合并区域内的所有行号加入集合 for (int row = startRow; row <= endAddr.getRow(); row++) { coveredRows.add(row); } mergeGroupMap.put(startRow, coveredRows); } }
2. 遍历工作表行,划分到对应集合
接下来遍历工作表的每一行,判断它属于哪个合并分组:如果是合并单元格的起始行,就新建一个集合;如果是合并区域内的其他行,就加入对应的集合里:
List<Set<Row>> groupSets = new ArrayList<>(); Set<Row> currentGroupSet = null; Integer currentMergeStartRow = null; for (CTRow ctRow : sheetData.getRowList()) { // 注意:CTRow的行号是1-based,普通Row对象是0-based,这里要做转换 int ctRowNum = ctRow.getR(); Row row = workSheet.getRow(ctRowNum - 1); // 检查当前行是否是某个合并分组的起始行 if (mergeGroupMap.containsKey(ctRowNum)) { // 新建集合并加入分组列表 currentGroupSet = new HashSet<>(); groupSets.add(currentGroupSet); currentMergeStartRow = ctRowNum; } // 如果当前行属于正在处理的合并分组,加入集合 if (currentGroupSet != null && mergeGroupMap.get(currentMergeStartRow).contains(ctRowNum)) { currentGroupSet.add(row); } }
3. 对每个集合单独处理
现在groupSets里的每个元素就是你要的set1、set2...,可以遍历这个列表,对每个集合执行自定义处理逻辑:
int groupCount = 1; for (Set<Row> group : groupSets) { System.out.println("开始处理集合set" + groupCount); // 这里替换成你的业务逻辑,比如读取单元格内容、计算等 for (Row row : group) { Cell targetCell = row.getCell(0); // 假设你要处理的是第一列 String cellContent = targetCell.getStringCellValue(); System.out.println("行" + row.getRowNum() + "的内容:" + cellContent); } groupCount++; }
几个要注意的细节
- 一定要注意POI中CT对象(比如
CTMergeCell、CTRow)的行号是1-based,而普通Row对象是0-based,转换的时候别搞混了 - 如果合并单元格是跨列的,但你只关注某一列的分组,需要额外判断单元格是否属于目标列
- 如果需要保持行的顺序,可以把
Set换成List,避免行顺序被打乱
内容的提问来源于stack exchange,提问作者Sathish Kumar k k
相关产品推荐
相关产品推荐

