You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用XWPF创建嵌套表格时内层表格垂直合并失效求助

问题排查:Apache POI XWPF嵌套表格内层单元格垂直合并不生效

问题现象

使用Apache POI的XWPF组件生成带嵌套表格的DOCX文档时,外层表格的单元格垂直合并功能正常,但内层表格的垂直合并完全不生效,与预期效果存在明显差异。

核心原因

Apache POI对嵌套表格的单元格垂直合并支持存在局限性:

  1. 直接复用外层表格的合并逻辑处理内层表格时,CTTcPr的vMerge属性无法被正确应用到内层表格的单元格上;
  2. 多数开发者会忽略:内层表格的每个参与合并的单元格都需要显式设置vMerge属性——首行单元格需设置restart标记,后续被合并的单元格需设置continue标记,而非仅给首行设置就完成配置。

修复方案

以下是调整后的代码示例,重点修正内层表格的垂直合并逻辑:

import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.io.FileOutputStream;
import java.io.IOException;

public class NestedTableMergeTest {
    public static void main(String[] args) throws IOException {
        XWPFDocument doc = new XWPFDocument();
        XWPFParagraph para = doc.createParagraph();
        XWPFRun run = para.createRun();
        run.setText("嵌套表格垂直合并测试");

        // 创建外层表格
        XWPFTable outerTable = doc.createTable(3, 2);
        // 外层表格垂直合并第一列前两行
        setVerticalMerge(outerTable.getRow(0).getCell(0), true);
        setVerticalMerge(outerTable.getRow(1).getCell(0), false);
        outerTable.getRow(0).getCell(0).setText("外层合并单元格");

        // 在内层表格所在的单元格创建嵌套表格
        XWPFTableCell innerTableCell = outerTable.getRow(0).getCell(1);
        innerTableCell.removeParagraph(0); // 清空默认段落,避免干扰表格渲染
        XWPFTable innerTable = innerTableCell.createTable(2, 2);

        // 内层表格垂直合并第一列两行
        setVerticalMerge(innerTable.getRow(0).getCell(0), true);
        setVerticalMerge(innerTable.getRow(1).getCell(0), false);
        innerTable.getRow(0).getCell(0).setText("内层合并单元格");
        innerTable.getRow(0).getCell(1).setText("内层单元格1");
        innerTable.getRow(1).getCell(1).setText("内层单元格2");

        // 写入文件
        try (FileOutputStream out = new FileOutputStream("nested_table_merge.docx")) {
            doc.write(out);
        }
        doc.close();
    }

    // 封装垂直合并设置方法
    private static void setVerticalMerge(XWPFTableCell cell, boolean isRestart) {
       CTTc ctTc = cell.getCTTc();
       CTTcPr tcPr = ctTc.getTcPr() == null ? ctTc.addNewTcPr() : ctTc.getTcPr();
       CTVMerge vMerge = tcPr.getVMerge() == null ? tcPr.addNewVMerge() : tcPr.getVMerge();
       if (isRestart) {
           vMerge.setVal(STVMerge.RESTART);
       } else {
           vMerge.setVal(STVMerge.CONTINUE);
       }
    }
}

关键说明

  • 必须为内层表格的每个参与合并的单元格单独设置vMerge属性,不能仅处理首行单元格;
  • 直接操作底层的CTTcPr和CTVMerge对象设置合并规则,避免依赖XWPF上层封装方法(上层方法对嵌套表格支持有限);
  • 嵌套表格所在的单元格需要先清空默认空段落,防止段落干扰表格的渲染逻辑。

内容的提问来源于stack exchange,提问作者keep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:45:57