根据网上的资料和自己在实践过程中整理总结一下用freemarker自定义导出word模板
1. 首先准备好一个Word模板
如图所示,我定义了一个很简单的模板,然后将所需变量用${}
副号定义,例:${username},如图所示
说明:这里填写变量的时候需要按照顺序
${username}
来填写,如果先填写了${}再写username的话,word转成xml文件时会出现问题,如图所示
2.定义好变量以后将Word另存为XML文件
将word文档另存为xml文件,如图所示
说明:网上有些人说选择Word XML文档时会有问题,还没验证过,所以这里选择的是Word 2003 XML
3.编辑打开XML文件
我这里选用Notepad++来打开的,如图所示
说明:刚转换完后,如果Notepad++没有安装XML格式化插件的话,打开的会是横着排列的一行,建议用Notepad++自带的插件浏览器下载XML插件,如图所示
下载方法:插件–>Plugin Manager–>Show Plugin Manager–>Available–>XML Tools–>Install
使用方法:插件–>XML Tools–>Pretty print(XML only - with line breaks)
4.编辑XML文件,另存为ftl文件
如果需要遍历出多行数据,则需要在<w:tr>
前加上list遍历,例:<#list newsList as listKey>
这里的newsList只是一个变量名称,里面的变量则需要listKey.username,后台其实就是用的Map<String,List>
,具体语法可参照
https://www.baidu.com/link?url=HsppryccH7jtBxyb-VOyQXOHAHlK0faxVuGUK8JBho2L6uKabgCltmsXXNTO_rahbx227tzAsfqu8m2PizwOsq&wd=&eqid=eb38bc4c000014650000000658ae53d5
这里的结构不难看出<w:tr>
为一行,<w:tc>
为一列,所以在<w:tr>
前后对应的位置加上<#list>
标签即可,编辑完后,将文件名称直接修改为.ftl文件即可,例如图所示
说明: 注意freemarker以及XML的语法结构
5.后台工具类编写
这里用的是java语言来编写的,附上源代码
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;
import org.apache.log4j.Logger;
import freemarker.template.Configuration;
import freemarker.template.Template;
/**
* @ClassName: WordUtil
* @Description: word模板
* @author sly.shuai
* @date2017年2月22日 上午9:55:35
* @version V1.0
*/
@SuppressWarnings("rawtypes")
public class WordUtil
{
private final static Logger logger = Logger.getLogger(WordUtil.class);
/**
* @Title: createWord
* @Description: 创建word
* @param dataMap
* word中展示的动态数据,用Map存储
* @param templatePath
* 模板存储路径
* @param templateName
* 模板名字
* @param filePath
* 生成word文件路径
* @param fileName
* 生成word文件名字 void
* @throws
* @变更记录 2017年2月22日 上午10:13:25 sly.shuai 创建
*/
public static void createWord(Map dataMap, String templatePath, String templateName, String filePath,
String fileName) {
Writer out = null;
try {
// 创建配置实例
Configuration configuration = new Configuration();
// 设置编码
configuration.setDefaultEncoding("UTF-8");
// ftl模板文件
configuration.setDirectoryForTemplateLoading(new File(templatePath));
// 获取模板
Template template = configuration.getTemplate(templateName);
// 输出文件
File outFile = new File(filePath + File.separator + fileName);
// 如果输出目标文件夹不存在,则创建
if (!outFile.getParentFile().exists()) {
outFile.getParentFile().mkdirs();
}
// 将模板和数据模型合并生成文件
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
// 生成文件
template.process(dataMap, out);
} catch (Exception e) {
logger.error("创建word出错:" + e);
throw new RuntimeException("创建word出错");
} finally {
try {
if (out != null) {
// 关闭流
out.flush();
out.close();
}
} catch (Exception e) {
logger.error("创建word出错:" + e);
}
}
}
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Ignore;
import org.junit.Test;
import com.yihuacomputer.yhcloud.service.util.WordPropertyUtil;
import com.yihuacomputer.yhcloud.service.util.WordUtil;
/**
* @ClassName: WordTest
* @Description: word导出测试
* @author sly.shuai
* @date2017年2月22日 上午10:35:32
* @version V1.0
*/
public class WordTest extends BaseSpringJunit
{
@Test
public void createWord() {
Map<String, Object> dataMap = new HashMap<String, Object>();
List<Map<String, Object>> newsList = new ArrayList<Map<String, Object>>();
for (int i = 1; i <= 10; i++) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("username", "用户名" + i);
map.put("password", "密码" + (i * 2));
map.put("phone", "电话" + (i * 3));
newsList.add(map);
}
dataMap.put("newsList", newsList);
WordUtil.createWord(dataMap, "/word/templatePath/", "test.ftl", "/word/filePath/", "test.doc");
}
}
说明:这里只是提供了一个公用工具类,dataMap是传入的数据,用Map封装List,运行测试用例即可在相应的目录下找到对应的文件