本文讲述读取word模板的制作和模板读取动态插入数据生成word
1.首先制作模板
找我们需要的word模板文件,打开他,然后选另存为,保存成XML格式
然后用Notepad++打开对应的XML,用XML Tools插件序列化数据(插件下载地址: 点这.)
序列化后处理数据占位符,删除${}包裹的中间不需要的格式标签字符.
然后保存,模板制作完成.
2.数据结合模板调用API生成文档实现下载
步骤大致如下:
1.设置下载响应头
2.处理数据,数据格式一般为Map<String,Object>格式
3.调用 freemarker的API方法完成下载.
参考代码如下:
//controller部分
@RequestMapping(value = "download/{caseId}", method = RequestMethod.GET)
public void downloadSimilarCase(HttpServletRequest request, HttpServletResponse response,
@RequestParam(value = "caseNo", required = false, defaultValue = "") String caseNo,
@PathVariable("caseId") String caseId) throws UnsupportedEncodingException {
// 文件名
caseNo = URLDecoder.decode(caseNo, "utf-8");
String fileName = AppUtils.encodeFileName(request.getHeader("User-Agent"), caseNo + ".doc");
service.getSimilarCaseById(response, caseId, fileName);
}
//service实现部分
public void getSimilarCaseById(HttpServletResponse response, String caseId, String fileName) {
//response.setContentType("application/vnd.ms-word;charset=UTF-8");
response.setContentType("application/msword;charset=UTF-8");
response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
response.setHeader("Content-Type", "application/force-download");
response.setCharacterEncoding("utf-8");
//condition 为动态写入的数据,他的键是占位符${}中介的字符,他的值就是对应需要替换改占位符的数据
Map<String, Object> condition = new HashMap<>();
condition.put("caseId", caseId);
Object result = getSimilarCaseById(condition);//调用方法获取数据,具体内容无需展开,自己按自己需求处理数据为Map<String, Object>格式即可
Map<String, Object> lawCase = null;
if(result instanceof Map) {
lawCase = (Map<String, Object>)result;
}
//这是清理脏数据的,如果你动态写入的内容里有一些特殊字符比如&,#等,可能会导致生成的文档无法打开,所以这里进行处理下
removeSpecChar(lawCase);
//这里就是拿处理好的数据和response相应流去实现浏览器响应下载,具体后面会展开说
CaseDocXmlUtils.create(response, lawCase);
}
// CaseDocXmlUtils.create(response, lawCase)方法详细内容
package com.futuredata.court.guide.web.util;
import com.futuredata.base.core.config.AppConfig;
import com.futuredata.base.core.util.AppUtils;
import com.futuredata.base.core.util.ZipUtils;
import com.futuredata.court.guide.web.model.LawsuitInfo;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.io.FileUtils;
import org.apache.http.util.TextUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletResponse;
public class CaseDocXmlUtils {
private static final Logger logger = LoggerFactory.getLogger(CaseDocXmlUtils.class);
private static final String REG_LAW_TAG = "<\\s*/?law([^>]*)>";
private static Configuration configuration = null;
static {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
//通过这个工具类的相对路径去找到存放模板xml的路径并读取
configuration.setClassForTemplateLoading(ReportUtils.class, "/template/");
}
public static void create(HttpServletResponse response, Map<String, Object> content) {
PrintWriter pw = null;
try {
pw = response.getWriter();
//这个是对数据的加工,本来data里面的值就是普通字符串文字,这里可以通过给文字加上一些word里面的xml标签,来实现文字样式格式的变化,这里具体不展开,插入的标签我举个例子,如下一个代码块里面的两个方法
Map<String, Object> data = getCaseDocData(content);
Template template = configuration.getTemplate((String)data.get("template"));
template.process(data, pw);
} catch (Exception ex) {
logger.error("生成word报表发生错误", ex);
} finally {
if (pw != null) {
pw.close();
}
}
}
}
//这就是给文字加样式格式的方法,将文字content加上上面标签再返回,到时候这一大串都会替换原来的占位符,成功进入xml文档,然后就能样式和文字生效展示
/**
* word换行.
*/
// private static String getWordText(String content) {
// return "<w:p>" + "<w:pPr>"
// + "<w:spacing w:before='100' w:after='100' w:line='380' w:lineRule='exact'/>"
// + "<w:ind w:firstLine='632'/>" + "<w:jc w:val='both'/>" + "<w:rPr>"
// + "<w:rFonts w:ascii='宋体' w:eastAsia='宋体' w:hAnsi='宋体' w:cs='宋体'/><w:color w:val='000000'/>"
// + "<w:sz w:val='28'/>" + "<w:u w:val='single'/>" + "</w:rPr>" + "</w:pPr>" + "<w:r>"
// + "<w:rPr>"
// + "<w:rFonts w:ascii='宋体' w:eastAsia='宋体' w:hAnsi='宋体' w:cs='宋体' w:hint='eastAsia'/><w:color w:val='000000'/>"
// + "<w:sz w:val='28'/>" + "</w:rPr>" + "<w:t>" + content + "</w:t>" + "</w:r>"
// + "<w:bookmarkStart w:id='0' w:name='_GoBack'/>" + "<w:bookmarkEnd w:id='0'/>" + "</w:p>";
// }
private static String getWordText(String content) {
return "<w:p><w:pPr><w:ind w:first-line='600'/><w:jc w:val='left'/></w:pPr><w:r><w:rPr>"
+ "<w:rFonts w:ascii='宋体' w:eastAsia='宋体' w:hAnsi='宋体' w:cs='宋体'/><w:color w:val='000000'/>"
+ "<w:sz w:val='32'/></w:rPr><w:t>"
+ content + "</w:t></w:r></w:p>";
}
/**
* word换行. 文字居右
* @param content
* @return
*/
private static String getWordTextRight(String content) {
return "<w:p>" + "<w:pPr>"
+ "<w:spacing w:before='100' w:after='100' w:line='380' w:lineRule='exact'/>"
+ "<w:jc w:val='right'/>" + "<w:rPr>"
+ "<w:rFonts w:ascii='宋体' w:eastAsia='宋体' w:hAnsi='宋体' w:cs='宋体'/><w:color w:val='000000'/>"
+ "<w:sz w:val='32'/>" + "<w:u w:val='single'/>" + "</w:rPr>" + "</w:pPr>" + "<w:r>"
+ "<w:rPr>"
+ "<w:rFonts w:ascii='宋体' w:eastAsia='宋体' w:hAnsi='宋体' w:cs='宋体' w:hint='eastAsia'/><w:color w:val='000000'/>"
+ "<w:sz w:val='32'/>" + "</w:rPr>" + "<w:t>" + content + "</w:t>" + "</w:r>"
+ "<w:bookmarkStart w:id='0' w:name='_GoBack'/>" + "<w:bookmarkEnd w:id='0'/>" + "</w:p>";
}
**结尾:**不知不觉写的有点啰嗦可能还不清晰哎,就先这样把,不懂可以留言问我,欢迎交流.