前言
在工作中有遇到需要在一个固定的word 模板中填充相关的数据,最终形成一份完成word 文档形式的报告。简单一些的可能只是对模板进行文字和数值的填充,稍微复杂一些的是模板中除了文本数值之外,还混合的有表格(可以循环遍历填充)、不规则表格(无序的,只能按照格子进行填充)、图片、条形图柱状图等。
本次主要介绍的插件是一个开源的操作word文档的组件,名为 POI-tl ,是一款基于Apache poi 打造的,官网地址为:http://deepoove.com/poi-tl/ 。
简述Apache Poi
在以往用Apache poi 进行操作word 文档时,我们通常这样操作:
- 根据模板存放的路径,获取到文件的输入流,然后创建XWPFDocument 对象。
- 获取word 文档中的所有段落,getParagraphs()。
- 循环遍历所有段落,获取到每个段落中的每一句话。getRuns()。
- 替换runs 中的文本text
以下代码为简单实例, poi 操作word 相对比较繁琐,word模板中的占位符需要自己进行定义,我习惯使用${}的形式,也有人直接使用{}。
String path = "";
File file = new File(path);
FileOutputStream os = null;
FileInputStream is = new FileInputStream(file);
XWPFDocument doc = new XWPFDocument(is);
// 替换文本
List<XWPFParagraph> paragraphs = doc.getParagraphs();
if (paragraphs != null && paragraphs.size() > 0){
for(XWPFParagraph paragraph:paragraphs){
List<XWPFRun> runs=paragraph.getRuns();
for(int i=0;i<runs.size();i++){
String text=runs.get(i).getText(0);
text=text.replace("${name}","创作不易,给个鼓励");
runs.get(i).setText(text,0);
}
}
}
//替换表格内容
List<XWPFTable> tables = doc.getTables();
for (int i = 0; i < tables.size(); i++){
XWPFTable xwpfTable=tables.get(i);
XWPFTableRow defRow=xwpfTable.getRow(3);
setTextColorAndFont(row,"张三"),0);
setTextColorAndFont(row,"北京",1);
setTextColorAndFont(row,"程序员",2);
setTextColorAndFont(row,"25",3);
setTextColorAndFont(row,"138336287882"),4);
}
/**
*row 行对象
*tbText 单元格要填充的内容
*cellIndex 单元格的下标
*/
public void setTextColorAndFont(XWPFTableRow row,String tbText, int cellIndex) {
tbText = checkValueIsNull(tbText);
XWPFTableCell cell = row.getCell(cellIndex);
List<XWPFParagraph> paragraphs = cell.getParagraphs();
XWPFParagraph xwpfParagraph = paragraphs.get(0);
XWPFRun xpfr = xwpfParagraph.createRun();
xpfr.setFontFamily("宋体");
xpfr.setFontSize(12);
xpfr.setText(tbText);
}
Poi-tl 上手实操
安装使用步骤可以详见API文档,这里不做过多的赘述。http://deepoove.com/poi-tl/#_%E5%89%8D%E6%8F%90http://deepoove.com/poi-tl/#_%E5%89%8D%E6%8F%90
简单的一些操作直接看在线文档就可以搞定, 我在这里主要说一下复杂一些的表格生成,以及在开发过程遇到的坑。
- poi-tl 中, word 模板中的占位符需要设置为{ {name}} 这种形式。
- 如果word 模板中内容很多,那么在一个类里面要写的代码就会很多,也没有办法进行协同编码,因为都在一个类中写代码的话,每次合并代码就会很麻烦,所以我们采用讲word模板分段来实现的方式。
-
AutoAwareZgybHandlerFactory.getTemplateHandler(param.getClass()); 通过获取TemplateHandler 的这种方式,