需求:根据数据库已有字段,填入写好的word并下载
工具 :freemark 一种方便生成word的引擎,内置好大量基础方法
思路:
一.将数据库数据按需求(根据id,根据name......)提取存储在一个map中待用
二.将模板word生成ftl文件,以便freemark来改造
三.将存有数据的map依靠WordUtils工具类传递数据给ftl
四.前台连接,生成word
详解:
步骤一
1.按照需求,根据id查找一个po实例,使用到sql语句查询
mapping:
<select id="findById" parameterType="String"
resultType="com.kanq.ly.pwf.model.PwfContract">
select t.* from PWF_CONTRACT t where t.id = #{id}
</select>
ctrl:
private String downloadWord(HttpServletRequest request,HttpServletResponse response,String id) throws IOException{
//根据id获取一个实例
System.out.println("合同id:"+id);
PwfContract pwfContract=getEntryById(id);
//map中存放需要生成word文档的合同具体信息
Map<String, Object> mapValue = new HashMap<String, Object>();
mapValue.put("cdate", pwfContract.getCdate());
mapValue.put("category", pwfContract.getCategory());
//利用工具类生成文档,需要修改工具类的具体信息
WordUtils.exportMillCertificateWord(request,response,mapValue);
return null;
}
步骤二:
1.把word模板中需要填充的数据进行修改 ,把 a 改成 ${a}
注意!!!此时存在一个问题:当a为空的时候,后台会报一个null的错误,freemark无法自动填充一个null值,需要进行判断,把 a改成 <#if a??> ${(a)!""}</#if>意思为如果a不存在 a的值默认为"",!是默认的意思,
所以最后把a修改成<#if a??> ${(a)!""}</#if>,然后保存文件类型为xml
2.把xml的文件打开,会观察到 <#if a??> ${(a)!""} 这句话会被填充一些字符(这些字符是word文档一些修饰的东西,比如说字体大小颜色粗细之类的),需要把这些填充的字符删除,只留下纯粹的<#if a??> ${(a)!""}这句话,然后保存为ftl的文件
注意!!!freemark这个引擎填充数据的原理是通过对照字段,比如在map中存放的字段为 name 在ftl中就会找name的字段填充进去,如果对应不上,就无法填充,无字段前后顺序要求
步骤三;
1.首先需要一个WordUtils工具类,百度上一大堆,用来查找ftl文件位置以及整合map
package com.kanq.framework.utils.tool;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URLEncoder;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import freemarker.template.Configuration;
import freemarker.template.Template;
public class WordUtils {
//配置信息,代码本身写的还是很可读的,就不过多注解了
private static Configuration configuration = null;
//这里注意的是利用WordUtils的类加载器动态获得模板文件的位置 ,修改ftl文件的位置 类加载器获取数据源 路径 获取路径
private static final String templateFolder = WordUtils.class.getClassLoader().getResource("../../").getPath() + "pages/wordTemplate";
static {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
try {
//引擎搜索ftl文件的基础路径设置
configuration.setDirectoryForTemplateLoading(new File(templateFolder));
} catch (IOException e) {
e.printStackTrace();
}
}
private WordUtils() {
throw new AssertionError();
}
public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map) throws IOException {
//在默认路径上找到相应的ftl文件
Template freemarkerTemplate = configuration.getTemplate("pwf.ftl");
File file = null;
InputStream fin = null;
ServletOutputStream out = null;
try {
// 调用工具类的createDoc方法生成Word文档
file = createDoc(map,freemarkerTemplate);
fin = new FileInputStream(file);
//设置响应类型是文档
response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
// 设置浏览器以下载的方式处理该文件名
String fileName = "管护合同.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 = "管护合同.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;
}
}
该工具类的主要方法为:createDoc(map元数据,ftl文件){} 根据map源数据生成doc文件
exportMillCertificateWord(请求,响应,map元数据){} 配置生成doc的环境
2.在ctrl中利用WordUtils中的exportMillCertificateWord生成一个Word
WordUtils.exportMillCertificateWord(request,response,mapValue);
步骤四:
1.html中添加超链传递id
<a href="javascript:void(0)" οnclick="pwfContract.exportWord('{{id}}')">生成合同</a>
2.js中接收id传递给后台
var exportWord = function(id){
window.open("../pwf/pwfContract/downloadWord.do?id="+id);}
3.后台接收id,作为查询po实例关键字
@RequestMapping(value="downloadWord.do")
private String downloadWord(HttpServletRequest request,HttpServletResponse response,String id) throws IOException{
//根据id获取一个实例
System.out.println("合同id:"+id);
PwfContract pwfContract=getEntryById(id);}