FreeMarker
是一款模板引擎:即一种基于模板、用来生成输出文本(任何来自于HTML格式的文本用来自动生成源代码)的通用工具。 使用MVC模式的动态页面的设计构思使得你可以将前端设计师(编写HTML页面的人员)从程序员中分离出来。本文为使用 freemarker 来生成 word 文档的示例。
工具
- Word2003 以上版本或者 wps2016 的版本(即可以支持文档另存为
xml
格式的版本) - jar包:
freemark.jar
第一步:数据准备
- 一张图片:1.jpg
- 一个word文档。内容如下:
第二步:制作模板
- 把word文档另存为
.xml
格式,我起名称为template.xml
- 利用
Notepad++
或者sublime text
这样的工具打开template.xml
文件。 - 利用
Ctrl+F
搜索word中你写的信息,如:小明、男...等关键字找到template.xml
中对应的字,用${name}
、${sex}
等值代替,${}
中的值为代码中要赋值的变量。 - 搜索
<pkg:binarydata>
和</pkg:binarydata>
会发现这俩标签之间是一堆特别特别长的字符。像是这样:
把中间的字符替换成
${image}
,如图:
4.把替换好的template.xml
文件后缀名改为.ftl
。至此,模板制作成功。
第三步:编写代码
基于 SpringMVC ,简单写了个 Demo。
页面 index.jsp
<body>
<center>
<div style="padding: 3px 2px; border-bottom: 1px solid #ccc">填写相关数据进行导出</div>
<form name="form" action="" method="post">
<table>
<tr>
<td>姓名:</td>
<td><input name="name" type="text"></input></td>
</tr>
<tr>
<td>性别:</td>
<td><input id="man" name="sex" type="radio" value='1' checked />男
<input id="woman" name="sex" type="radio" value='0' />女</td>
</tr>
<tr>
<td>生日:</td>
<td><input name="birthday" type="text"></input></td>
</tr>
<tr>
<td>电话:</td>
<td><input name="telphone" type="text"></input></td>
</tr>
<tr>
<td>邮箱:</td>
<td><input name="email" type="text"></input></td>
</tr>
<tr>
<td>地址:</td>
<td><input name="address" type="text"></input></td>
</tr>
<tr>
<td>头像路径:</td>
<td><input id="photo" name="photo" type="text" /></td>
</tr>
</table>
<br>
<table>
<tr>
<input type="button" value="导出Word" onclick="exportData('word')">
</tr>
</table>
</form>
</center>
</body>
<script type="text/javascript">
function exportData(obj) {
if (obj == "word") {
form.action = "${pageContext.request.contextPath}/exportWord.action";
form.submit();
}
}
function showPreview(obj){
var str = obj.value;
document.getElementById("previewImg").innerHTML = "![]( + str + )";
}
</script>
工具类 ExportWorldUtil.java
package com.export.util;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.Map;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import sun.misc.BASE64Encoder;
/**
* 数据导出World工具类
*
* @author qixiantong
*
*/
public class ExportWorldUtil {
private Configuration configuration;
public void configure(String templatePath) {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
configuration.setClassForTemplateLoading(this.getClass(), templatePath);
}
public void create(String templatePath, String templateName, String filePath, String fileName,
Map<String, Object> map) {
this.configure(templatePath);
Template template = null;
try {
// 读取freemarker的导出模板
template = configuration.getTemplate(templateName);
} catch (IOException e) {
e.printStackTrace();
}
// 创建一个file对象
File outFile = new File(filePath + fileName);
// 写入字符流的抽象类
Writer out = null;
try {
// 创建一个使用默认大小输出缓冲区的缓冲字符输出流
// OutputStreamWriter 字节-字符转换流
// FileOutputStream 文件输出流
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (map != null) {
try {
// 执行模板,使用提供的数据模型
template.process(map, out);
out.close();
} catch (TemplateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 由于word中图片为base64编码, 故将图片转化为base64编码后的字符串
* @author qixiantong
* @return String
*/
public String getImageStr(String imgFile) {
// String imgFile = new File(this.getClass().getResource("/").getPath())
// + "/com/export/doc/1.jpg";
InputStream in = null;
byte[] data = null;
try {
// 创建照片的字节输入流
in = new FileInputStream(imgFile);
// 创建一个长度为照片总大小的内存空间
data = new byte[in.available()];
// 从输入流中读取文件大小的字节,并将其存储在缓冲区数组 data中
in.read(data);
// 关闭输入流
in.close();
} catch (IOException e) {
e.printStackTrace();
}
BASE64Encoder encoder = new BASE64Encoder();
// 进行base64加密
return encoder.encode(data);
}
}
控制器 ExportDataAction.java
/**
* 起始页面
*
* @return
*/
@RequestMapping("/index")
public String login() {
return "index";
}
/**
* 导出到Word
*
* @author zhang_cq
* @return
*/
@RequestMapping("/exportWord")
public String exportWord(HttpServletRequest request, Person person) {
try {
ExportWorldUtil util = new ExportWorldUtil();
String templatePath = "../doc/"; // 模板路径
String templateName = "template.ftl"; // 模板名称
String filePath = "d:/";
String fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".doc"; // 生成的World文档路径
ExportWorldUtil ewu = new ExportWorldUtil();
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", person.getName());
String sex = person.getSex();
map.put("sex", "1".equals(sex) ? "男" : "女");
String imagePath = person.getPhoto();
//imagePath = imagePath.replace("\\", "/");
map.put("image", util.getImageStr(imagePath));
SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date birthday = person.getBirthday();
if (birthday != null) {
String birth = bartDateFormat.format(birthday);
map.put("birthday", birth);
}
map.put("telphone", person.getTelphone());
map.put("email", person.getEmail());
map.put("address", person.getAddress());
ewu.create(templatePath, templateName, filePath, fileName, map);
} catch (Exception e) {
e.printStackTrace();
}
return "index";
}
// 使用注解进行日期格式数据转换
@InitBinder
private void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
// 指定日期类型及日期数据的格式
// 日期类型要和student类的birthday一致
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
}
至此,在 java 中 生成 word 文档的实例就做完了。想看完整代码,欢迎访问https://coding.net/u/zhang_cq/p/ExportData/git