import java.awt.Color; import java.awt.Rectangle; import java.io.FileOutputStream; import java.io.IOException; import org.apache.poi.sl.usermodel.TableCell.BorderEdge; import org.apache.poi.xslf.usermodel.XMLSlideShow; import org.apache.poi.xslf.usermodel.XSLFSlide; import org.apache.poi.xslf.usermodel.XSLFTable; import org.apache.poi.xslf.usermodel.XSLFTableCell; import org.apache.poi.xslf.usermodel.XSLFTableRow; /** * Demonstrate problem with mergeCell rowspan in single column table * (POI writes out the rowspan=... to XML, but MS PowerPoint ignores it) */ public final class TestMergeCells { private TestMergeCells() {} // Populate a table private static void fillTable(XSLFTable tbl, int numRows, int numColumns, Color clr) { for (int r = 0; r < numRows; r++) { XSLFTableRow tr = tbl.addRow(); tr.setHeight(50); for (int c = 0; c < numColumns; c++) { XSLFTableCell cell = tr.addCell(); cell.setText("Row" + r + " Col" + c); cell.setBorderColor(BorderEdge.bottom, clr); cell.setBorderColor(BorderEdge.left, clr); cell.setBorderColor(BorderEdge.top, clr); cell.setBorderColor(BorderEdge.right, clr); } } } // Workaround function - should POI be doing this internally? private static void mergeCellsMod(XSLFTable tbl, int fromRow, int toRow, int fromCol, int toCol) { if (tbl.getNumberOfColumns() == 1) { double h = tbl.getRowHeight(fromRow); // accumulate spanned-over row heights as we remove them for (int r = toRow; r > fromRow; --r) { h += tbl.getRowHeight(r); tbl.removeRow(r); } tbl.setRowHeight(fromRow, h); } else { tbl.mergeCells(fromRow, toRow, fromCol, toCol); } } public static void main(String[] args) throws IOException{ try (XMLSlideShow ppt = new XMLSlideShow()) { XSLFSlide slide = ppt.createSlide(); // Red table has 2 columns, shows that merging rows works (and in 2nd column we demonstrate workaround function) XSLFTable ta = slide.createTable(); ta.setAnchor(new Rectangle(50, 50, 300, 200)); fillTable(ta, 4, 2, Color.red); // 4 rows, 2 cols // Blue Table has 1 column, shows that mergeCells is ineffective here when viewed in MS PowerPoint v2108 XSLFTable tb = slide.createTable(); tb.setAnchor(new Rectangle(400, 50, 150, 200)); fillTable(tb, 4, 1, Color.blue); // 4 rows, 1 col // Green table, demonstrate basic workaround technique for row spans in single column tables XSLFTable tc = slide.createTable(); tc.setAnchor(new Rectangle(200, 300, 150, 200)); fillTable(tc, 4, 1, Color.green); // 4 rows, 1 col tc.removeRow(2); tc.setRowHeight(1, 100); // set height to 2x50 // Magenta table demonstrates use a function to apply the workaround XSLFTable td = slide.createTable(); td.setAnchor(new Rectangle(500, 300, 150, 200)); fillTable(td, 4, 1, Color.magenta); // 4 rows, 1 col // Merge middle cells in first columns ta.mergeCells(1,2,0,0); // has the desired effect in 2-col table mergeCellsMod(ta, 0,1,1,1); // test workaround function on 2-col table mergeCellsMod(ta, 2,3,1,1); // ...and again tb.mergeCells(1,2,0,0); // MS PowerPoint ignores rowspan request in single column table! mergeCellsMod(td, 1, 2, 0, 0); try (FileOutputStream out = new FileOutputStream("TestMergeCells.pptx")) { ppt.write(out); } } } }