实践总结-freemarker生成word模板

一、项目需求描述:

根据获取的计算模型计算的结果生成一个word模型固定的word报告。

计算结果结构如下:


7786310-5c8f0c26d5aa85d3.png
数据结构

原始word模板如下:


7786310-adf3f4cae6bb1d92.png
原始word模板

预期输出结果如下:


7786310-b70a9159dcaac44b.png
预期结果1


7786310-786c52a62a808eb0.png
预期结果2


7786310-25ed1dbc3bc1e161.png
预期结果3

代码实现思路:

通过word xml生成flt模板文件此处注意word版本,此次实践涉及的word xml标签及freemarker标签详见上篇《word xml + freemarker生成模板文件》

通过freemarker相关jar包中提供的方法,封装一个freemarker模板处理类(代码下面贴出);

使用模板处理类接收HashMap类型的数据,key值对应在flt文件中使用的占位符的名称;

将数据来源进行一系列业务处理,进行分类、统计,最后用HashMap对其进行包装,产生freemarker模板中所需的所有变量的值的HashMap;


代码实现:

1、freemarker模板类

```

importfreemarker.template.Configuration;

importfreemarker.template.Template;

importfreemarker.template.TemplateException;

importjava.io.*;

importjava.util.HashMap;

importjava.util.Map;

public classDocumentHandler {

privateConfigurationconfiguration=null;

privateStringencoding="utf-8";

privateStringtemplatePath;

privateStringtemplateName;

privateMapdataMap;

privateStringsaveFileDir="";

privateStringfileName;

privateStringreturnFileFullPath;

publicDocumentHandler() {

configuration=newConfiguration();

}

public voidcreateDoc(String saveFileDir,String fileName,String encoding,String templatePath,String templateName,Map datasource) {

InitParas(saveFileDir,fileName,encoding,templatePath,templateName,

datasource);

this.createDoc();

}

private voidInitParas(String saveFileDir,String fileName,

String encoding,String templatePath,String templateName,

Map datasource) {

this.saveFileDir= saveFileDir;

this.fileName= fileName;

this.encoding= encoding;

this.templatePath= templatePath;

this.templateName= templateName;

this.dataMap= datasource;

configuration.setDefaultEncoding(this.encoding);

//设置模本装置方法和路径FreeMarker支持多种模板装载方法。可以从servlet,classpath,数据库装载

//这里我们的模板是放在dist.dgp.template包下

configuration.setClassForTemplateLoading(this.getClass(), this.templatePath);

}

public voidcreateDoc() {

configuration.setDefaultEncoding(this.encoding);

//设置模本装置方法和路径FreeMarker支持多种模板装载方法。可以从servlet,classpath,数据库装载

//这里我们的模板是放在com.havenliu.document.template包下

configuration.setClassForTemplateLoading(this.getClass(), this.templatePath);

//要填入模版的数据文件

if(null==dataMap){

System.out.println("警告,模板数据源为空。");

dataMap=newHashMap();

}

try{

//装载的模板名称

Template t =configuration.getTemplate(this.templateName);

//输出文档路径

File outDir =newFile(this.saveFileDir);

if(!outDir.exists()){

outDir.mkdirs();

}

File outFile =newFile(outDir.getAbsolutePath()+"/"+this.fileName);

Writer out =null;

//此编码必须得跟模板的编码是一致的,否则打开生成的word,提示xml非法字符

out =newBufferedWriter(newOutputStreamWriter(newFileOutputStream(outFile),this.encoding));

t.process(dataMap,out);

if(outFile.exists()){

this.returnFileFullPath= outFile.getAbsolutePath();

System.out.println(returnFileFullPath);

}else{

this.returnFileFullPath="";

}

}catch(IOException e) {

e.printStackTrace();

}catch(TemplateException e) {

e.printStackTrace();

}

}

getter、setter...

}

```

2、业务处理后使用HashMap进行包装

```

//模板内值对应实体

//用地统计-管理单元总量分析计算结果

dataMap.put("totalManagementList",totalManagementList);

//用地统计-编制单元总量分析计算结果

dataMap.put("compilationList",compilationList);

//公服配置-管理单元-子类型计算结果

dataMap.put("managementUnitPSMap",manageUnitPSSubMap);

//公服配置-编制单元-子类型计算结果

dataMap.put("compilationUnitPSMap",compilationUnitPSSubMap);

```

3.在flt模板文件中使用freemarker标签,进行文件内容填充


7786310-d69b2dde23a03f30.png
flt模板文件内容形式--管理单元总量分析计算结果



7786310-fd6882ff50cf9671.png
flt模板文件内容形式--编制单元总量分析计算结果


7786310-5ea2a3141311e73c.png
flt模板文件内容形式--编制单元公服配置子类型


7786310-ce341b9bd376ede4.png
flt模板文件内容形式--编制单元公服配置子类型中的计算结果

管理单元公服配置与编制单元公服配置形式相同。

4.模板生成方法:

```

private  DocumentHandler  doc;

doc.setDataMap(dataMap);//数据源

doc.setTemplateName(this.templateName);

doc.setSaveFileDir(SystemUtil.getProjectPhysicalPath() +fileSaveDir);//生成文件保存路径

doc.setFileName(newIPTimeStamp().getIPTimeStampRandom() +"."

+this.fileExtension);

doc.createDoc();//生成文档

```

生成成功后就可以在指定的路径下去查看文件了。