How to merge cells (or apply colspan) using XWPFTable in POI in Java?
Asked Answered
D

3

10

Creating a table in poi was quite easy but it has very limited tutorials and I cannot find one that can create a simple merged cell in a table in generating a docx file.

Dit answered 13/4, 2013 at 6:18 Comment(0)
E
14

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) example of a vertical merge (image with example)

 // 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);
Eddyede answered 15/12, 2016 at 23:10 Comment(3)
Your solution worked for me, but I add to slightly modify it by adding : if (cell.getCTTc().getTcPr() == null) cell.getCTTc().addNewTcPr();Pilewort
Why supegroupRow.getCell(0).getCTTc().getTcPr() is null?V2
Thanks, worked for me. As the syntax is quite complicated i wrote a helper method: 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); } }Guilt
D
10

If you have created table, row inside a table and cell inside a row, you can add gridSpan to cell properties:

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

Note: cell is org.apache.poi.xwpf.usermodel.XWPFTableCell.

Divisor answered 28/8, 2013 at 14:0 Comment(0)
G
7

Creating a separate XWPFTable for each table row will work and should be perfectly fine. All the tables are merged behind the scenes to one table in the final word document. You will need all of these jars, poi-3.9.jar, poi-ooxml-3.9.jar and poi-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));
}
Gera answered 14/5, 2014 at 1:36 Comment(3)
Sure, I voted this answer up. I don't think there is a way I can accept as answer, since I did not ask the original question. Let me know if this is actually possible.Interior
Hi, I tried using this, and it does correctly set the span of a cell, but I have left over cells outside the table (to the right) equal to the span size. I tried to trim these off by removing them with XWPFTableRow.removeCell( pos ). I confirmed that they are removed in the java row object, but when the table renders and is viewed in Word, they are still there. Do you know how to get these excess cells to go away?Interior
I didn't understand clearly, but for each table, total span must be the same. If it is not equal, you will see extra columns, first fix total span by determining largest row, for example a row with 15 columns, then in my answer first table will have 15 span in first column, second table can have 5 in each of 3 columns.Gera

© 2022 - 2024 — McMap. All rights reserved.