java 使用 poi 对指定 excel 的指定多列进行从左到右树形行合并

java 复制代码
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.util.*;

public class MyExcelUtils {

    private static final String seperator = UUID.randomUUID().toString().replaceAll( "-","" );

    public static void main(String[] args) throws IOException {
        List<Integer> colIndexs = new ArrayList<>();
        colIndexs.add( 0 );
        colIndexs.add( 1 );
        colIndexs.add( 2 );
        String inputPath = "D:\\xxx\\test.xlsx";
        String outputPath = "D:\\xxx\\output.xlsx";
        doRowMerge( colIndexs,inputPath,outputPath );
    }

    /** ps: Workbook 中 excel 的第一行的 rowIndex = 0,第一列的 colIndex = 0
     * 对指定 excel 的指定列进行行合并( 按照从做到右的树形行合并 )
     * @param colIndexList_needRowMerge
     * @param inputExcelPath
     * @param outputExcelPath
     */
    public static void doRowMerge( List<Integer> colIndexList_needRowMerge,String inputExcelPath,String outputExcelPath ) throws IOException {
        //  校验:colIndexList_needRowMerge 中不能出现重复 的 colIndex
        if( new HashSet<Integer>( colIndexList_needRowMerge ).size() < colIndexList_needRowMerge.size() ){
            throw new RuntimeException( "操作失败,There are duplicate elements in the list colIndexList_needRowMerge" );
        }
        //  对 colIndexList_needRowMerge 中的 colIndex 排序(从小到大)
        Collections.sort( colIndexList_needRowMerge );
        if( colIndexList_needRowMerge == null || colIndexList_needRowMerge.size() == 0 ){
            return;
        }
        inputExcelPath = MyStringUtils.null2EmptyWithTrim( inputExcelPath );
        outputExcelPath = MyStringUtils.null2EmptyWithTrim( outputExcelPath );
        if( inputExcelPath.length() == 0 || outputExcelPath.length() == 0 ){
            return;
        }
        //  对临时 excel 进行行合并
        Workbook workbook = null;
        try {
            workbook = new XSSFWorkbook( new FileInputStream( new File( inputExcelPath ) ) );
            Sheet sheet = workbook.getSheetAt(0);
            int lastRowIndex = sheet.getLastRowNum();

            for( Integer colIndex:colIndexList_needRowMerge ){
                int startRowIndex = 0;
                int endRowIndex = startRowIndex;

                String cellContent_prevRow = getCellContent_withPrevCols( sheet,0,colIndex,colIndexList_needRowMerge );
                System.out.println( cellContent_prevRow );
                for (int rowIndex = 1; rowIndex <= lastRowIndex; rowIndex++) {
                    String cellContent_currRow = getCellContent_withPrevCols( sheet,rowIndex,colIndex,colIndexList_needRowMerge );
                    if( cellContent_currRow.equals( cellContent_prevRow ) ){
                        endRowIndex++;
                    }else {
                        if( ( endRowIndex - startRowIndex ) >= 1 ){
                            sheet.addMergedRegion( new CellRangeAddress( startRowIndex, endRowIndex, colIndex, colIndex ) );
                            System.out.println( "合并第" + colIndex + "列的 " + startRowIndex + "行~" + endRowIndex + "行" );
                        }
                        startRowIndex = endRowIndex + 1;
                        endRowIndex = startRowIndex;
                        cellContent_prevRow = cellContent_currRow;
                    }
                }
                System.out.println( "startRowIndex = " + startRowIndex );
                System.out.println( "endRowIndex = " + endRowIndex );
                if( ( endRowIndex - startRowIndex ) >= 1 ){
                    sheet.addMergedRegion( new CellRangeAddress( startRowIndex, endRowIndex, colIndex, colIndex ) );
                    System.out.println( "合并第" + colIndex + "列的 " + startRowIndex + "行~" + endRowIndex + "行" );
                }
            }
            workbook.write( new FileOutputStream( new File( outputExcelPath )) );
            System.out.println("Cells merged successfully!");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if( workbook != null ){
                workbook.close();
            }
        }
    }

    private static String getCellContent_withPrevCols(Sheet sheet, int rowIndex,int colIndex,List<Integer> colIndexList_needRowMerge ) {
        String cellContent = "";
        for( Integer colIndex_:colIndexList_needRowMerge ){
            if( colIndex_ <= colIndex ){
                cellContent += sheet.getRow( rowIndex ).getCell( colIndex_ ).getStringCellValue();
                cellContent += seperator;
            }else {
                break;
            }
        }
        return cellContent;
    }
}

示例:

  1. 原始 excel:
  1. 对前三列进行合并后的 excel:
相关推荐
码智社17 分钟前
Java实现RSA密钥生成、加密解密、加签验签
java
wear工程师26 分钟前
ThreadLocal 在线程池里为什么会串数据:别只会答内存泄漏
java·后端
Iruoyaoxh26 分钟前
栈和队列~
java·开发语言
审小匠OpenCPAi31 分钟前
银行流水核查怎么自动化?单边匹配、双向勾稽与图聚类异常检测的工程对比
java·前端·人工智能·python·审计
Hrain-AI34 分钟前
2026 企业 AI 编程智能体实战:Codex 与 Claude Code
开发语言·人工智能·kotlin
码上上班1 小时前
docker课程
java·docker·容器
腻害兔1 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:CRM 客户关系模块深度解析——从线索到回款,一套完整的 B2B 销售闭环是怎么搭的?
java·前端·javascript·vue.js·产品经理·ai编程
wdfk_prog1 小时前
嵌入式面试真题第 13 题:单硬件 Timer 下的高精度多路软件定时器架构设计
c语言·开发语言·面试·职场和发展·嵌入式
oort1231 小时前
吃上了自家的细糠,还挺丝滑,用起来手感还行,OortCloud发布新版AI编程平台,下载 OortCodex,Token多,免费薅
大数据·开发语言·人工智能·ai编程
达子6661 小时前
第9章_HarmonyOs图解 用Java开发UI
java·ui·harmonyos