我正在尝试使用 apache poi 在 powerpoint 幻灯片中的现有示例表中创建新行而不丢失格式,但仍然无法获取它。
我希望添加一行时会有一个与上一行具有相同样式的新行,但是并没有保持样式。
我试图这样做,但我不能,因为不可能有 XSLFTable 的实例。尝试在另一个主题中搜索答案,但其他场景与允许保持风格的 XSFTable 相关。
XSLFTableRow oldRow = table.getRows().get(1);
CTRow ctrow = CTRow.Factory.parse(oldRow.getXmlObject().newInputStream());
XSLFTableRow newRow = new XSLFTableRow(ctrow, table); //Not possible to do this for ppt table
XSLFTableCell cell = newRow.addCell();
XSLFTextParagraph paragraph = cell.addNewTextParagraph();
XSLFTextRun textRun = paragraph.addNewTextRun();
textRun.setText("User 2");
感谢您的帮助。
文本表格,例如 Word 表格和 PowerPoint 表格,确实是野兽。 Apache POI 开发人员做出了非常不同的、有时令人难以理解的决定来处理这些野兽。
对于 PowerPoint 表格,可以使用 XSLFTable.addRow 向当前表格添加新行。但这只会添加一个具有默认高度的新空行,请参阅XSLFTable.java。
要获得上一行的完整副本,可以调用 XSLFTableRow 构造函数
XSLFTableRow(CTTableRow row, XSLFTable table)
拥有 CTTableRow row
上一个表行的 CTTableRow
的完整副本。但该构造函数不是公共的,而是仅在内部打包。为什么?我不知道。
幸运的是,如果某些东西不是公开的,Java 中有反射来获取它。
因此,我们可以像
XSLFTable.addRow
那样使用 CTTableRow row
做前一个表行 CTTableRow
的完整副本。
之后,我们有一个新的表行,它是前一个表行的精确副本。
完整示例:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.xslf.usermodel.*;
public class PPTXAddTableRow {
static XSLFTableRow addTableRow(XSLFTable table) throws Exception {
XSLFTableRow lastRow = table.getRows().get(table.getNumberOfRows()-1);
org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow ctTableRowLastRow = lastRow.getXmlObject();
java.lang.reflect.Field __table = XSLFTable.class.getDeclaredField("_table");
__table.setAccessible(true);
org.openxmlformats.schemas.drawingml.x2006.main.CTTable _table = (org.openxmlformats.schemas.drawingml.x2006.main.CTTable)__table.get(table);
org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow ctTableRowNew = _table.addNewTr();
ctTableRowNew.set(ctTableRowLastRow.copy());
java.lang.reflect.Constructor constructor = XSLFTableRow.class.getDeclaredConstructor(org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow.class, XSLFTable.class);
constructor.setAccessible(true);
XSLFTableRow newRow = (XSLFTableRow)constructor.newInstance(ctTableRowNew, table);
java.lang.reflect.Field __rows = XSLFTable.class.getDeclaredField("_rows");
__rows.setAccessible(true);
@SuppressWarnings("unchecked")
java.util.List<XSLFTableRow> _rows = (java.util.List<XSLFTableRow>)__rows.get(table);
_rows.add(newRow);
java.lang.reflect.Method updateRowColIndexes = XSLFTable.class.getDeclaredMethod("updateRowColIndexes");
updateRowColIndexes.setAccessible(true);
updateRowColIndexes.invoke(table);
return newRow;
}
public static void main(String[] args) throws Exception {
XMLSlideShow slideShow = new XMLSlideShow(new FileInputStream("./TableSample.pptx"));
for (XSLFSlide slide : slideShow.getSlides()) {
for (XSLFShape shape : slide.getShapes()) {
if (shape instanceof XSLFTable) {
XSLFTable table = (XSLFTable)shape;
XSLFTableRow newTableRow = addTableRow(table);
for (XSLFTableCell cell : newTableRow.getCells()) {
cell.setText("new text");
}
}
}
}
FileOutputStream out = new FileOutputStream("./TableSampleNew.pptx");
slideShow.write(out);
out.close();
slideShow.close();
}
}
注意这里使用
XSLFTableCell.setText
是为了简化。但这会丢失可能的文本段落和文本运行格式。因此,可能需要使用 XSLFTableCell
-XSLFTextShape
的文本段落和文本运行,而不是 XSLFTableCell.setText
。