java poi 之 word 模板导出(1)

首先百科一下POI是什么:

Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。通过字面意思,我们大概知道这个API是可以用来做 java 导出word 及excel 的。下面不废话了,直接总结一下,java 用模板导出 word 的方法。目前项目中我用到的方法分为两种(今天先说第一种)。

1.使用poi读取模板word,然后导出所需要的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 后缀名。然后就是准备好替换的模板,如下图:

java poi 之 word 模板导出(1)_第1张图片

下面直接上代码,注意看步骤:

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

下面看看替换后的效果:

java poi 之 word 模板导出(1)_第2张图片

好像是成功了,但大家注意了!格式不对啊

下面说一个解决方法

//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

好了,看看结果:

java poi 之 word 模板导出(1)_第3张图片

替换成功,到此第一种方法告一段落了。

补充:有些童鞋反应有时候会出现替换不成功的问题,如下所示:

java poi 之 word 模板导出(1)_第4张图片

这里说一下原因:这里在poi读取模板的文件的时候会先把word 转为 xml 格式然后转为ftl
格式,这中间转换会发生一些意想不到的问题!如下图:

大家看到,变为ftl格式以后,这个${day} 就被拆分了。正确应该是这样的

所以,我们得手动改下。或者先把word保存为xml格式再写${}符号。完美解决变量不替换问题。好了,今天先写到这里,下次有时间再说一下第二种方法。

你可能感兴趣的:(poi)