POI XWPFTable多行垂直合并导致表格异常问题排查
问题描述
我有一个4×4的XWPFTable实例sampleTable,想要将前三列实现垂直合并(每列的4行合并为一个单元格)。但运行以下代码后:
XWPFTable sampleTable=sampleDOCX.createTable(4, 4); for(int col=0;col<3;col++){ for(int row=0;row<4;row++){ XWPFTableCell cell=sampleTable.getRow(row).getCell(col); if(row==0){ cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART); }else{ cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE); } } }
得到的表格中前两列的行莫名被删除,且检查XML后发现,第一行的0、1号单元格并未添加<w:vMerge w:val="restart"/>标签——也就是STMerge.RESTART完全没生效,请问这是什么原因?
问题原因与解决方法
核心原因
POI创建表格时,会对前几列的单元格默认启用样式共享机制,即多个单元格复用同一个CTTcPr(单元格属性)对象。你的代码里直接调用addNewTcPr(),会覆盖原有共享的属性配置,导致第一行设置的restart被后续行的continue操作冲掉,最终前两列的合并配置失效,甚至触发单元格被删除的异常。
修正代码
操作单元格属性时,要先检查是否已有TcPr对象,优先复用而非直接新建,这样能避免破坏POI的样式共享逻辑:
XWPFTable sampleTable = sampleDOCX.createTable(4, 4); for(int col = 0; col < 3; col++){ for(int row = 0; row < 4; row++){ XWPFTableCell cell = sampleTable.getRow(row).getCell(col); // 先获取现有TcPr,不存在再新建 CTTcPr tcPr = cell.getCTTc().getTcPr(); if (tcPr == null) { tcPr = cell.getCTTc().addNewTcPr(); } // 先获取现有VMerge,不存在再新建 CTVMerge vMerge = tcPr.getVMerge(); if (vMerge == null) { vMerge = tcPr.addNewVMerge(); } // 设置合并类型 if(row == 0){ vMerge.setVal(STMerge.RESTART); }else{ vMerge.setVal(STMerge.CONTINUE); } } }
内容的提问来源于stack exchange,提问作者Adnan
相关产品推荐
相关产品推荐

