一、 制作模板
如下图,我们一般需要给出固定模板,按照模板通过freemarker语法写成图二的格式,然后另存为xml格式,最后通过更改后缀名改为ftl页面。
图解:
- 给出模板
2. 通过freemarker语法把需要从数据库取出的来值抽象化
此处的user为别名
3. 另存为XML文件
4. 打开之后的界面
因为不是很利于阅读和修改,所以我们放在idea或者在线格式化工具中进行格式化。这里我用idea进行格式化。
5. 然后我们进行编辑,我们使用freemarker语法进行循环取值。
在文件中搜索 ‘<w:body>’ 关键字,在该标签后面 添加 <#list list as user> 在搜索 </w:body> 标签,在该标签前面添加 </#list> 标签。如下图所示:
注意:
图中红框部分必须为一个整体,如果中间多了一些标签和其他元素,直接删掉即可
- 然后我们进行图片处理,直接搜索<w:pict> 标签,我们会看到,下图所示的图片信息(当word另存为xml的时候,其中的图片会以Base64编码形式展示在xml文件的特定位置)
我们需要把<w:binData></w:binData>之间的Base64图片信息改成freemarker语法。这里不需要担心图片的样式问题,你在word上制作模板的时候把图片的样式调整为你想要的即可,结果输出的时候也会是你制作模板的样式。如下图所示:
- 把全部代码另存为 .ftl 后缀的文件,或者直接改后缀也可以。把文件放在需要的地方。
这样我们的模板就算改好了。下来就是代码实现的问题了。
二、 代码实现读取数据库数据 ,并输出到word文档上
- 读取数据库,获取数据。代码如下:
public void geeneratorWord (String id, HttpServletResponse response, HttpServletRequest request) {
try {
//桌面
String filePath="C:/Users/lenovo/Desktop/";
//ftl 文件名称
String ftlName="test_ft.ftl";
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("userIds", id);
List<HashMap<String, Object>> data = (List<HashMap<String, Object>>) dao.get("test.sql.generatorWord", params);
//word 中的数据
List<HashMap<String, Object>> mapList = new ArrayList<HashMap<String, Object>>();
//循环取出来的用户信息,有几个用户,生成几个
for (int i = 0; i < data.size(); i++) {
HashMap<String, Object> userMap = new HashMap<String, Object>();
//放user 信息
userMap.put("user_name", data.get(i).get("user_name"));
userMap.put("org_name", data.get(i).get("org_name"));
userMap.put("job_name", data.get(i).get("job_name"));
userMap.put("code_no", data.get(i).get("code_num"));
userMap.put("project_name", data.get(i).get("project_name"));
//头像信息
String imgAvatar = "";
//头像存储路径
String imgAvatarPic = "";
imgAvatar =(String) data.get(i).get("avatar");
if (StringUtils.isNotBlank(imgAvatar)) {
//存到库的人员头像信息
imgAvatarPic = WordUtil.getImageBase(new File(filePath + data.get(i).get("file_name")));
}else {
//人员照片不存在,展示默认照片
imgAvatarPic = WordUtil.getImageBase(new File(filePath + "default.png"));
}
userMap.put("photo", imgAvatarPic);
//把用户信息,添加到list中
mapList.add(userMap);
}
HashMap<String, Object> wordList = new HashMap<String, Object>();
wordList.put("list", mapList);
//生成word文档
WordUtil.exportMillCertificateWord(response, wordList,ftlName);
} catch (IOException e) {
e.printStackTrace();
}
}
- 生成word文档工具类
public class WordUtil {
private static Configuration configuration = null;
static {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
try {
File file = new File("C:/Users/lenovo/Desktop/");
if(!file.exists()){
file.mkdirs();
}
configuration.setDirectoryForTemplateLoading(file);
} catch (IOException e) {
e.printStackTrace();
}
}
private WordUtil() {
throw new AssertionError();
}
/**
* @author dzk
* @param response
* @param list
* @throws IOException
*/
public static void exportMillCertificateWord(HttpServletResponse response, Map list,String ftlName) throws IOException {
Template freemarkerTemplate = configuration.getTemplate(ftlName);
File file = null;
InputStream fin = null;
ServletOutputStream out = null;
try {
// 调用工具类的createDoc方法生成Word文档
file = createDoc(list,freemarkerTemplate);
fin = new FileInputStream(file);
response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
// 设置浏览器以下载的方式处理该文件名
String fileName = "temp"+ DateFormatUtils.format(new Date(),"yyyyMMddHHmmss") + ".doc";
response.setHeader("Content-Disposition", "attachment;filename="
.concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
out = response.getOutputStream();
byte[] buffer = new byte[512]; // 缓冲区
int bytesToRead = -1;
// 通过循环将读入的Word文件的内容输出到浏览器中
while((bytesToRead = fin.read(buffer)) != -1) {
out.write(buffer, 0, bytesToRead);
}
} finally {
if(fin != null) fin.close();
if(out != null) out.close();
if(file != null) file.delete(); // 删除临时文件
}
}
private static File createDoc(Map<?, ?> dataMap, Template template) {
String name = "temp.doc";
File f = new File(name);
Template t = template;
try {
// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
t.process(dataMap, w);
w.close();
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
return f;
}
//获得图片的base64码
public static String getImageBase(File file) {
if(!file.exists()) {
return "";
}
InputStream in = null;
byte[] data = null;
try {
in = new FileInputStream(file);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
try {
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);
}
// main
// public static void main(String[] args) {
// /*String path =WordUtils.class.getClassLoader().getResource("../../").getPath() + "WEB-INF/templetes/";*/
// System.out.println(WordUtil.class.getResource("").toString());
// }
}
freemarker版本和commons-lang版本
org.freemarker:freemarker:2.3.29
org.apache.commons:commons-lang3:3.6
- 效果图
综上,就可以根据模板生成我们想要的word文档啦。