POI版本3.14
用下面的代码生成一个带表格的pptx文件:
public static void makeTablePpt() throws Exception{
//创建ppt
XMLSlideShow ppt = new XMLSlideShow();
//创建ppt页
XSLFSlide slide = ppt.createSlide();
//添加一个2行2列表格
XSLFTable table = slide.createTable(2, 2);
//获取第一行
XSLFTableRow row = table.getRows().get(0);
//获取第一行第一列
XSLFTableCell cell = row.getCells().get(0);
//格子赋值
cell.setText("a");
cell.setText("b");
OutputStream os = new FileOutputStream("e:/table.pptx");
ppt.write(os);
os.close();
}
发现报错:java.lang.IndexOutOfBoundsException: Index: 1, Size: 1。
如果XSLFTableCell只执行一次setText是不会报错的。
查看出错的源码:
public XSLFTextRun setText(String text) {
if(!this._paragraphs.isEmpty()) {
CTTextBody txBody = this.getTextBody(false);
int cntPs = txBody.sizeOfPArray();
for(int i = cntPs; i > 1; --i) {
txBody.removeP(i - 1);
this._paragraphs.remove(i - 1);
}
((XSLFTextParagraph)this._paragraphs.get(0)).clearButKeepProperties();
}
return this.appendText(text, false);
}
是在操作_paragraphs属性的时候出错的,感觉应该是poi的bug。XSLFTableCell继承自XSLFTextShape,有属性:
private final List<XSLFTextParagraph> _paragraphs = new ArrayList();存放文本段落。
XSLFTextParagraph有属性
private final List<XSLFTextRun> _runs;
存放文本。
可以直接操作XSLFTextRun来改变格子的值。
解决方法:
封装一个方法来改变表格的值:
private static void setCellValue(XSLFTableCell c, String txt) {
XSLFTextParagraph tp = c.getTextParagraphs().isEmpty() ?
c.addNewTextParagraph() : c.getTextParagraphs().get(0);
XSLFTextRun run = tp.getTextRuns().isEmpty() ?
tp.addNewTextRun() : tp.getTextRuns().get(0);
run.setText(txt);
}
于是上面的代码改为:
public static void makeTablePpt() throws Exception{
//创建ppt
XMLSlideShow ppt = new XMLSlideShow();
//创建ppt页
XSLFSlide slide = ppt.createSlide();
//添加一个2行2列表格
XSLFTable table = slide.createTable(2, 2);
//获取第一行
XSLFTableRow row = table.getRows().get(0);
//获取第一行第一列
XSLFTableCell cell = row.getCells().get(0);
//格子赋值
setCellValue(cell, "a");
setCellValue(cell, "b");
OutputStream os = new FileOutputStream("e:/table.pptx");
ppt.write(os);
os.close();
}