如何在Java中使用POI的XWPFTable合并单元格(或应用colspan)?

9

在poi中创建一个表格是比较容易的,但是教程非常有限,我找不到一个可以在生成docx文件时创建一个简单合并单元格的表格的教程。

3个回答

12
To merge horizontally/vertically, you need to create 2 CTHMerge and use the setVal:
- one for the cells that you will remain (STMerge.RESTART); - a second one for the merged cells (STMerge.CONTINUE);
a) Example for a horizontal merge for 2x2 table (image with example): |______| --> |___________| |______| --> | |
 // First Row
CTHMerge hMerge = CTHMerge.Factory.newInstance();
hMerge.setVal(STMerge.RESTART);
table.getRow(0).getCell(0).getCTTc().getTcPr().setHMerge(hMerge);
table.getRow(1).getCell(0).getCTTc().getTcPr().setHMerge(hMerge);

 // Secound Row cell will be merged/"deleted"
CTHMerge hMerge1 = CTHMerge.Factory.newInstance();
hMerge1.setVal(STMerge.CONTINUE);
table.getRow(0).getCell(1).getCTTc().getTcPr().setHMerge(hMerge1);
table.getRow(1).getCell(1).getCTTc().getTcPr().setHMerge(hMerge1);
b) 垂直合并示例 (带有示例图像)
 // First Row
CTVMerge vmerge = CTVMerge.Factory.newInstance();
vmerge.setVal(STMerge.RESTART);
table.getRow(0).getCell(0).getCTTc().getTcPr().setVMerge(vmerge);
table.getRow(0).getCell(1).getCTTc().getTcPr().setVMerge(vmerge);
 
 // Secound Row cell will be merged 
CTVMerge vmerge1 = CTVMerge.Factory.newInstance();
vmerge1.setVal(STMerge.CONTINUE);
table.getRow(1).getCell(0).getCTTc().getTcPr().setVMerge(vmerge1);
table.getRow(1).getCell(1).getCTTc().getTcPr().setVMerge(vmerge1);

4
你的解决方案对我有效,但我需要稍微修改它,即添加以下内容: if (cell.getCTTc().getTcPr() == null) cell.getCTTc().addNewTcPr(); - IronRabbit
1
为什么supergroupRow.getCell(0).getCTTc().getTcPr()为空? - Ekaterina Ivanova iceja.net
谢谢,对我很有帮助。由于语法相当复杂,我编写了一个辅助方法:private static void mergeCellsHorizontally(XWPFTable table, int rowNr, int cellFrom, int cellTo) { CTHMerge mergeStart = CTHMerge.Factory.newInstance(); mergeStart.setVal(STMerge.RESTART); table.getRow(rowNr).getCell(cellFrom).getCTTc().getTcPr().setHMerge(mergeStart); for (int i = cellFrom + 1; i <= cellTo; i++) { CTHMerge mergeContinue = CTHMerge.Factory.newInstance(); mergeContinue.setVal(STMerge.CONTINUE); table.getRow(rowNr).getCell(i).getCTTc().getTcPr().setHMerge(mergeContinue); } } - Wexoo

10

如果您已经创建了表格、表格中的行和行中的单元格,您可以在单元格属性中添加gridSpan:

if (cell.getCTTc().getTcPr() == null) cell.getCTTc().addNewTcPr();
if (cell.getCTTc().getTcPr().getGridSpan() == null) cell.getCTTc().getTcPr().addNewGridSpan();
cell.getCTTc().getTcPr().getGridSpan().setVal(2);

注意: cell 是 org.apache.poi.xwpf.usermodel.XWPFTableCell

5

为每个表格行创建一个单独的XWPFTable将起作用,并且应该完全没有问题。在最终的Word文档中,所有表格都在后台合并成一个表格。您需要这些JAR文件:poi-3.9.jarpoi-ooxml-3.9.jarpoi-ooxml-schemas-3.9.jar

XWPFTable table1 = document.createTable(1,1); // This is your row 1
XWPFTable table2 = document.createTable(1,3); // This is your row 2

// Now it's time to span each column of table1 and table2 to a span of your choice
// lets say 6 is the total span required assuming there's some row with 6 columns.

spanCellsAcrossRow(table1, 0, 0, 6);
spanCellsAcrossRow(table2, 0, 0, 2);
spanCellsAcrossRow(table2, 0, 1, 2);
spanCellsAcrossRow(table2, 0, 2, 2);

private void spanCellsAcrossRow(XWPFTable table, int rowNum, int colNum, int span) {
    XWPFTableCell  cell = table.getRow(rowNum).getCell(colNum);
    cell.getCTTc().getTcPr().addNewGridSpan();
    cell.getCTTc().getTcPr().getGridSpan().setVal(BigInteger.valueOf((long)span));
}

当然,我投了这个答案的赞。我不认为有一种方法可以接受作为答案,因为我没有提出原始问题。如果可能的话,请告诉我。 - Dan Torrey
嗨,我尝试使用这个,它确实可以正确设置单元格的跨度,但是我在表格外(向右)留下了剩余的单元格,数量等于跨度大小。我尝试通过使用XWPFTableRow.removeCell(pos)来删除它们以修剪它们。我确认它们在Java行对象中被删除了,但是当表格呈现并在Word中查看时,它们仍然存在。您知道如何让这些多余的单元格消失吗? - Dan Torrey
1
我没有很清楚理解,但是对于每个表格来说,总跨度必须相同。如果不相等,你将会看到额外的列。第一步要通过确定具有最多列的行来修正总跨度,例如一行有15列,在我的回答中第一个表格的第一列将会有15个跨度,第二个表格的三列中每列可以有5个跨度。 - Narayana Nagireddi
1
谢谢。这完全有道理。我感激您的帮助。 - Dan Torrey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接