You need to enable JavaScript to run this app. Apache POI Word 新创建行无法垂直合并单元格如何解决
优惠活动
大模型
产品
解决方案
定价
更多

Apache POI Word 新创建行无法垂直合并单元格如何解决

解决方案

问题根源是手动解析CTRow构造XWPFTableRow再插入表格的方式,会导致新行单元格与表格的内部关联属性缺失,后续设置的垂直合并标记无法被Word正确识别,最终合并失效。

你可以按照以下步骤修改代码,无需拆分保存读取流程即可实现需求:

  1. 替换自定义创建新行的逻辑,使用XWPFTable原生的插入行方法创建新行,再复制原行的样式和内容,保证表格内部属性关联正常
  2. 合并方法中新增原有垂直合并属性的清理逻辑,避免残留属性干扰

修改后的完整可运行代码如下:

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

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

public class POIWordAddSubRowQuestionDemo{
    public static void main(String[] args) throws IOException{
        ClassLoader classLoader = POIWordAddSubRowQuestionDemo.class.getClassLoader();
        InputStream inputStream = classLoader.getResourceAsStream("input.docx");
        String outputDocxPath = "F:/TEMP/output.docx";
        assert inputStream != null;
        XWPFDocument doc = new XWPFDocument(inputStream);
        XWPFTable table = doc.getTables().get(0);
        //this is 'old row 2'
        XWPFTableRow secondRow = table.getRows().get(1);

        // 替换原来的自定义行创建逻辑,使用原生插入行方法
        XWPFTableRow newRow = table.insertNewTableRow(2);
        // 复制old row 2的所有单元格样式和内容
        for (int i = 0; i < secondRow.getTableCells().size(); i++) {
            XWPFTableCell sourceCell = secondRow.getCell(i);
            XWPFTableCell targetCell = newRow.addNewTableCell();
            // 复制单元格样式
            if (sourceCell.getCTTc().isSetTcPr()) {
                targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());
            }
            // 复制段落内容
            targetCell.removeParagraph(0);
            for (XWPFParagraph sourcePara : sourceCell.getParagraphs()) {
                XWPFParagraph targetPara = targetCell.addParagraph();
                targetPara.getCTP().set(sourcePara.getCTP());
            }
        }
        // 设置新行第二列文本
        XWPFRun xwpfRun = newRow.getCell(1).getParagraphs().get(0).getRuns().get(0);
        xwpfRun.setText("new row", 0);

        //merge cells at first column of 'old row 2', 'new row', and 'old row 3'
        mergeCellVertically(doc.getTables().get(0), 0, 1, 3);

        FileOutputStream fos = new FileOutputStream(outputDocxPath);
        doc.write(fos);
        fos.close();
        doc.close();
    }

    static void mergeCellVertically(XWPFTable table, int col, int fromRow, int toRow) {
        for(int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
            XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
            CTVMerge vmerge = CTVMerge.Factory.newInstance();
            if(rowIndex == fromRow){
                // 首个合并单元格设置RESTART标记
                vmerge.setVal(STMerge.RESTART);
            } else {
                // 合并到首格的单元格设置CONTINUE标记并清空内容
                vmerge.setVal(STMerge.CONTINUE);
                for (int i = cell.getParagraphs().size(); i > 0; i--) {
                    cell.removeParagraph(0);
                }
                cell.addParagraph();
            }
            CTTcPr tcPr = cell.getCTTc().getTcPr();
            if (tcPr == null) tcPr = cell.getCTTc().addNewTcPr();
            // 先清空原有垂直合并标记,避免残留干扰
            if (tcPr.isSetVMerge()) {
                tcPr.unsetVMerge();
            }
            tcPr.setVMerge(vmerge);
        }
    }
}

修改后直接运行即可实现你需要的合并效果,无需额外的保存读取步骤。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 22:15:09