前言
因为工作任务填充word的模板,之前用的最多的是excel。 第一次操作word,面向百度开发,遇到了很多问题,也找了很多bolg。 百度有很多标题与内容不符的blog, 找的有点心累,现在做一个总结。
版本:5.0.0
在线Api: http://poi.apache.org/apidocs/5.0/
问题总结
- XWPFRun 分段问题
- 在指定位置填充表格
- 在表格里面插入表格
- 插入图片
- 单元格合并
未解决的问题:在word里面插入附件
解决问题
XWPFRun 分段问题
例如我要替换word里面的${name}
和${year}
在poi分段的时候可能会分成这样的段落
${
nam
e}
${
year
}
解决方法:
- 网上的解决方案是 在text里面写标记然后在复制粘贴到word
这种方法太麻烦 - 用一个临时变量存储标记
XWPFDocument document = new XWPFDocument(in);
List<XWPFParagraph> pars = document.getParagraphs();
StringBuilder builder;
for (XWPFParagraph pg : pars) {
if (pg.getText().contains("$")) {
builder = new StringBuilder();
// 获取分词
List<XWPFRun> runs = pg.getRuns();
boolean start = false;
String text;
for (XWPFRun run : runs) {
text = run.text();
if (text.startsWith("$")) {
start = true;
}
if (start) {
builder.append(text);
// 清除标记
run.setText("", 0);
}
if (text.endsWith("}")) {
start = false;
// 获取到完整标记
// TODO 业务逻辑
System.out.println(builder.toString());
}
}
}
}
在指定位置插入一个表格
我在word里面打了一个${table}标记,要在这个地方插入一个表格
··· 找到该段落
// 首先获取段落游标
XmlCursor cursor = pg.getCTP().newCursor();
// 跳到下一行
cursor.toNextSibling();
// 然后根据游标插入一个表格
XWPFTable table = document.insertNewTbl(cursor);
// 创建行
XWPFTableRow row = table.createRow();
// 创建单元格
XWPFTableCell cell = row.createCell();
新插入的表格只有一行一列,也就是只有一个单元格。并且创建第一行填充多少格,后续行就是多少格,不用再创建单元格了
在表格里面插入表格
XmlCursor cursor = pg.getCTP().newCursor();
cursor.toNextSibling();
XWPFTable table = document.insertNewTbl(cursor);
// document 插入的表格只有一行一格
XWPFTableCell cell = table.getRow(0).getCell(0);
// 添加段落
XWPFParagraph cellPg = cell.addParagraph();
// 创建一个文本区域
XWPFRun cellRun = cellPg.createRun();
cellRun.setText("天青色等烟雨");
// 获取游标
XmlCursor c = cell.addParagraph().getCTP().newCursor();
// 游标下移
c.toNextSibling();
// 插入表格
XWPFTable cellTable = cell.insertNewTbl(c);
// 这个表格第一行不能使用,删除掉
cellTable.removeRow(0);
// 填充内容
cellTable.createRow().createCell().setText("而我在等你");
结果:
这里只是做一个演示,表格里面插入的表格没有边框,需要手动设置边框属性。
private static void setBorders(XWPFTable table) {
table.getRows().forEach(row -> {
row.getTableCells().forEach(cell -> {
// 自动宽度
cell.setWidthType(TableWidthType.AUTO);
CTTcBorders borders = null;
if (cell.getCTTc().addNewTcPr().getTcBorders() == null) {
borders = cell.getCTTc().addNewTcPr().addNewTcBorders();
}
// 上下左右
setBorder(borders.addNewTop());
setBorder(borders.addNewBottom());
setBorder(borders.addNewLeft());
setBorder(borders.addNewRight());
});
});
}
private static void setBorder(CTBorder border) {
// 设置单实线
border.setVal(STBorder.SINGLE);
// 宽度
border.setSz(BigInteger.valueOf(2));
border.setColor("000000");
}
效果: