Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。通过字面意思,我们大概知道这个API是可以用来做 java 导出word 及excel 的。下面不废话了,直接总结一下,java 用模板导出 word 的方法。目前项目中我用到的方法分为两种(今天先说第一种)。
先说一下准备工作:
1.1 所需jar 包:这里我使用的是poi-3.9 jar 包,下面上依赖:
org.apache.poi
poi-ooxml
3.9
org.apache.poi
ooxml-schemas
1.1
1.2 模板文件 xxxx.docx
这里要说一下有一个小坑,poi-3.9 目前只支持读取 .docx 格式的 word,也就是office 2007以后的格式。请大家注意使用时把 word 模板改为 .docx 后缀名。然后就是准备好替换的模板,如下图:
下面直接上代码,注意看步骤:
String path = request.getSession().getServletContext().getRealPath("/exceldemo/关于安排2017年市级机关住房解困资金的报告.docx");//获取模板路径
FileInputStream is = new FileInputStream(path);//读入流中
XWPFDocument xdf = new XWPFDocument(is);//新建一个word文档
//变量
Map params = new HashMap();
params.put("year", year);
params.put("month", month);
params.put("day", day);
params.put("win",win);
this.replaceText(xdf,params);//替换word中的变量。
这里用了一个方法replaceText(),就是替换变量的方法,代码如下:
/**
* 替换文档中的参数(word)
* @param doc
* @param params
*/
private void replaceText(XWPFDocument doc, Map params) {
Iterator iterator = doc.getParagraphsIterator();
XWPFParagraph para;
while (iterator.hasNext()) {
para = iterator.next();
this.replaceInPara(para, params);
}
}
/**
* 替换段落中的参数(word)
* @param para
* @param params
*/
private void replaceInPara(XWPFParagraph para, Map params) {
List runs;
Matcher matcher;
if (matcher(para.getParagraphText()).find()) {
runs = para.getRuns();
for (int i=0; i
下面看看替换后的效果:
好像是成功了,但大家注意了!格式不对啊
下面说一个解决方法
//1.读取工作簿word模板
String path = request.getSession().getServletContext().getRealPath("/exceldemo/关于安排2017年市级机关住房解困资金的报告.docx");
String tempPath = request.getSession().getServletContext().getRealPath("/exceldemo/关于安排2017年市级机关住房解困资金的报告1.docx");
FileInputStream is = new FileInputStream(path);
FileInputStream tempIs = new FileInputStream(tempPath);
XWPFDocument xdf = new XWPFDocument(is);
XWPFDocument tempXdf = new XWPFDocument(tempIs);
this.replaceText(xdf,params);
this.setStyle(tempXdf,xdf);//tempXdf-模板的格式,xdf-模板
注意 this.setStyle(tempXdf,xdf) 这个方法就是按模板样式替换生成的word。即你要准备两个一样的模板,一个用来替换参数,一个用来替换格式!下面上代码
/**
* 处理文档替换内容的格式问题(word)
* @param tempDoc
* @param doc
*/
private void setStyle(XWPFDocument tempDoc,XWPFDocument doc) {
Iterator iterator = tempDoc.getParagraphsIterator();
Iterator iterator2 = doc.getParagraphsIterator();
XWPFParagraph para ;
XWPFParagraph para2;
while (iterator.hasNext()&&iterator2.hasNext()) {
para = iterator.next();
para2 = iterator2.next();
this.setStyleInPara(para,para2);
}
}
/**
* 处理段落替换内容的格式问题(word)
* @param para
* @param para2
*/
private void setStyleInPara(XWPFParagraph para, XWPFParagraph para2) {
List runs;
List runs2;
Matcher matcher;
if (matcher(para.getParagraphText()).find()) {
runs = para.getRuns();
runs2 = para2.getRuns();
for (int i=0; i
好了,看看结果:
替换成功,到此第一种方法告一段落了。
补充:有些童鞋反应有时候会出现替换不成功的问题,如下所示:
这里说一下原因:这里在poi读取模板的文件的时候会先把word 转为 xml 格式然后转为ftl
格式,这中间转换会发生一些意想不到的问题!如下图:
大家看到,变为ftl格式以后,这个${day} 就被拆分了。正确应该是这样的
所以,我们得手动改下。或者先把word保存为xml格式再写${}符号。完美解决变量不替换问题。好了,今天先写到这里,下次有时间再说一下第二种方法。