思路:文档模板—>freemarker处理内容–>导出
一、准备模板
准备一个word文档:
${}——这是freemarker的表达式(大致都和thymeleaf和jsp差不多),后面通过java去设置title的值,待会在解释
具体表达式请参照学习官方网站:http://freemarker.foofun.cn/index.html
word模板整好后,保存格式(两种方式,为了图个方便我就保存为xml):
- 另存为“ word 文档 XML格式(*.xml)”
- 或者步骤1完成后,将后缀名(.xml)改成(.ftl)
提示:word格式尽量简单,不要过于花哨,否则导出的内容格式可能与模板不一致
二、使用Freemarker模板引擎
Freemarker是一个强大的模板引擎,不仅仅可以处理生成word,还支持生成HTML网页,电子邮件,配置文件,源代码等。
新建一个maven项目,以及导入模板,这是目录结构:
<!-- 导入依赖 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
实现预期word内容的循环以及标题设置,模板设置:
<!-- 由于模板xml文件过长,这里只展示文档内容 -->
<w:p>
<w:pPr>
<w:pStyle w:val="2"/>
<w:bidi w:val="0"/>
<w:jc w:val="center"/>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
<w:lang w:val="en-US" w:eastAsia="zh-CN"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
<w:lang w:val="en-US" w:eastAsia="zh-CN"/>
</w:rPr>
<w:t>${title}</w:t> <!-- 标题 -->
</w:r>
</w:p>
<w:tbl>
<w:tblPr>
<w:tblStyle w:val="4"/>
<w:tblW w:w="0" w:type="auto"/>
<w:tblInd w:w="0" w:type="dxa"/>
<w:tblBorders>
<w:top w:val="single" w:color="auto" w:sz="4" w:space="0"/>
<w:left w:val="single" w:color="auto" w:sz="4" w:space="0"/>
<w:bottom w:val="single" w:color="auto" w:sz="4" w:space="0"/>
<w:right w:val="single" w:color="auto" w:sz="4" w:space="0"/>
<w:insideH w:val="single" w:color="auto" w:sz="4" w:space="0"/>
<w:insideV w:val="single" w:color="auto" w:sz="4" w:space="0"/>
</w:tblBorders>
<w:tblLayout w:type="autofit"/>
<w:tblCellMar>
<w:left w:w="108" w:type="dxa"/>
<w:right w:w="108" w:type="dxa"/>
</w:tblCellMar>
</w:tblPr>
<w:tblGrid>
<w:gridCol w:w="8522"/>
</w:tblGrid>
<#list lists as bean> <!-- 这是freemarker的循环语法 -->
<w:tr>
<w:tblPrEx>
<w:tblBorders>
<w:top w:val="single" w:color="auto" w:sz="4" w:space="0"/>
<w:left w:val="single" w:color="auto" w:sz="4" w:space="0"/>
<w:bottom w:val="single" w:color="auto" w:sz="4" w:space="0"/>
<w:right w:val="single" w:color="auto" w:sz="4" w:space="0"/>
<w:insideH w:val="single" w:color="auto" w:sz="4" w:space="0"/>
<w:insideV w:val="single" w:color="auto" w:sz="4" w:space="0"/>
</w:tblBorders>
<w:tblCellMar>
<w:left w:w="108" w:type="dxa"/>
<w:right w:w="108" w:type="dxa"/>
</w:tblCellMar>
</w:tblPrEx>
<w:trPr>
<w:trHeight w:val="777" w:hRule="atLeast"/>
</w:trPr>
<w:tc>
<w:tcPr>
<w:tcW w:w="8522" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
<w:rPr>
<w:rFonts w:hint="default" w:asciiTheme="minorEastAsia"
w:hAnsiTheme="minorEastAsia" w:eastAsiaTheme="minorEastAsia"
w:cstheme="minorEastAsia"/>
<w:sz w:val="28"/>
<w:szCs w:val="28"/>
<w:vertAlign w:val="baseline"/>
<w:lang w:val="en-US" w:eastAsia="zh-CN"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:asciiTheme="minorEastAsia"
w:hAnsiTheme="minorEastAsia" w:cstheme="minorEastAsia"/>
<w:sz w:val="28"/>
<w:szCs w:val="28"/>
<w:vertAlign w:val="baseline"/>
<w:lang w:val="en-US" w:eastAsia="zh-CN"/>
</w:rPr>
<w:t>${bean}</w:t> <!-- 填入lists集合的内容 -->
</w:r>
</w:p>
</w:tc>
</w:tr>
</#list>
</w:tbl>
import freemarker.core.XMLOutputFormat;
import freemarker.template.Configuration;
import freemarker.template.Template;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Test {
public static void main(String[] args) throws FileNotFoundException {
String title = "使用Freemaker导出文档";
List<String> lists = new ArrayList<String>();
lists.add("内容1");
lists.add("内容2");
lists.add("内容3");
Map<String,Object> dataMap = new HashMap<String, Object>();
// 变量名必须与模板里设置的名字一致
dataMap.put("title", title);
dataMap.put("lists", lists);
getTempFile(dataMap, "template.xml");
}
// 配置信息可以自行查阅
public static Configuration getConfiguration() {
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("UTF-8");
// 对象属性为空时,避免抛出异常
configuration.setClassicCompatible(true);
configuration.setOutputFormat(XMLOutputFormat.INSTANCE);
// 模板路径
configuration.setClassForTemplateLoading(Test.class, "/template");
return configuration;
}
/**
* @param dataMap 参数
* @param templateName 模板名称
*/
public static File getTempFile(Map dataMap, String templateName) throws FileNotFoundException {
Template template = null;
Writer out = null;
// 临时文件
File outFile = null;
try {
template = getConfiguration().getTemplate(templateName);
String name = "导出" + (int) (Math.random() * 100000) + ".docx";
outFile = new File(name);
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"utf-8"));
// 模板整合内容
template.process(dataMap, out);
} catch (Exception e) {
e.printStackTrace();
} finally{ //finally下面的代码很重要 否则的话你导不出word 必须flush close 一下才行
if(out!=null){
try {
out.flush();
out.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
return outFile;
}
}