前言:另外一篇是手机端的word导出,需要兼容性,不然在安卓手机会乱码
freemarker模板导出word循环图片表格详细教程_Java大表哥的博客-CSDN博客 并且另存为模版格式不同数据绑定方式不同
一。整体环境:
二。功能需求:(数据需要导出成以下格式)
1.简单一点的文本类:
2.复杂一点的
三。准备工作:
先准备好Freemarker模版:步骤如下:
1.我们需要做的就是把需要导出到word的数据 使用${}替换下(这就相当于占位符)如图;
把需要导出的内容用占位符替换下
2.表格的:
3.改好之后把word另存为xml,然后通过在线的xml格式化通过notepad++打开,修改好格式:
(1).普通文本
这里截取一小部分
(2).表格的话需要在<w:tbl>标签内<w:tr>加上list标签,用来接收后面后端的数据:
加入list标签
list结束标签
序号并不是写死的,直接用<w:t>${zjl_index+1}</w:t>替换,(因为默认为0,所以加1)
最后把后缀改成.ftl就好了,过程:.word>.xml>.ftl。
四。开始后端编码
人狠话不多,直接贴编码:
1.controller层编码:
加载模版方法:freemarker加载模板目录的方法_Java大表哥的博客-CSDN博客
@RequestMapping(value = { "wordExportBySb" }, method = { RequestMethod.GET, RequestMethod.POST })
@ResponseBody
public void wordExportBySb(HttpServletRequest req, HttpServletResponse resp, String bgId) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException, TemplateException {
/** 初始化配置文件 **/
@SuppressWarnings("deprecation")
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
/** 加载模板 **/
//这个方法在eclipse跑是OK 的 打jar包部署获取不到模版
/*File file = ResourceUtils.getFile("classpath:templates");
configuration.setDirectoryForTemplateLoading(file);*/
// 这个方法在eclipse跑和打jar包部署都可以获取到模版
configuration.setClassForTemplateLoading(this.getClass(), "/templates");
Template template = configuration.getTemplate("研判报告上报模板.ftl");
XsCp xsCp = xsCpService.selectByPrimaryKey(bgId);//这里是我获取的业务对象
Map<String, Object> dataMap = new HashMap<>();
// ** 在ftl文件中有${bt}这个标签**//*
// Freemarder 数据必须不能为null
dataMap.put("bt", xsCp.getBt());
dataMap.put("sjdw", xsCp.getCjdw() == null ? "" : exportWordUtils.convertSjdw(xsCp.getCjdw()));
dataMap.put("cpms", xsCp.getBgms() == null ? "" : xsCp.getBgms());
dataMap.put("jyaq", xsCp.getJyaq() == null ? "" : xsCp.getJyaq());
//资金流转换
String ypZjl = xsCp.getYpZjl();
List<WordStreamVoBean> disposeZjlList = exportWordUtils.disposeZjl(ypZjl);//获取到list
if(disposeZjlList != null){
//循环获取到所有的数据
for (int i = 0; i < disposeZjlList.size(); i++) {
if ((disposeZjlList.get(i)).getBh() == null) {
disposeZjlList.get(i).setBh("");
}
if (disposeZjlList.get(i).getData() == null) {
disposeZjlList.get(i).setData("");
}
}
}
//添加资金流list:
dataMap.put("ypZjl", disposeZjlList);
//网络流转换
String ypWll= xsCp.getYpWll();
List<?> disposeWllList = exportWordUtils.disposeWll(ypWll);
if(disposeWllList != null){
for (int i = 0; i < disposeZjlList.size(); i++) {
if ((disposeZjlList.get(i)).getBh() == null) {
disposeZjlList.get(i).setBh("");
}
if (disposeZjlList.get(i).getData() == null) {
disposeZjlList.get(i).setData("");
}
}
}
dataMap.put("ypWll", disposeWllList);
//通讯流转换
String ypTxl= xsCp.getYpTxl();
List<WordStreamVoBean> disposeTxlList= exportWordUtils.disposeZjl(ypTxl);
if(disposeTxlList != null){
for (int i = 0; i < disposeTxlList.size(); i++) {
if ((disposeTxlList.get(i)).getBh() == null) {
disposeTxlList.get(i).setBh("");
}
if (disposeTxlList.get(i).getData() == null) {
disposeTxlList.get(i).setData("");
}
}
}
dataMap.put("ypTxl", disposeTxlList);
dataMap.put("ryList", ryList);
//..........其他业务和字段
dataMap.put("xybgz", xsCp.getXybgz() == null ? "" : xsCp.getXybgz());
//开始word导出:导出我没有写死导出到什么磁盘,是通过浏览器输出随意存放修改。
ServletOutputStream out = null;
String fileName = bt + ".doc";
try {
//utils里创建word的方法:后面会给出代码
File wordFile = ExportWordUtils.createDoc(dataMap, template);
fin = new FileInputStream(wordFile);
resp.setCharacterEncoding("utf-8");
resp.setContentType("application/msword");
resp.setHeader("Content-disposition", "attachment;filename=" + new String(fileName.getBytes("utf-8"), "ISO8859-1"));
out = resp.getOutputStream();
byte[] buffer = new byte[1024];// 缓冲区
int bytesToRead = -1;
// 通过循环将读入的Word文件的内容输出到浏览器中
while ((bytesToRead = fin.read(buffer)) != -1) {
out.write(buffer, 0, bytesToRead);
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (fin != null)
fin.close();
if (out != null)
out.close();
}
2.utils类方法:
public static File createDoc(Map<?,?> dataMap,Template template){
File f = new File("");
try{
//这个地方不能使用FileWriter因为需要指定编码类型否则生成的word文档会因为有无法识别的编码而无法打开
Writer w = new OutputStreamWriter(new FileOutputStream(f),"utf-8");
template.process(dataMap,w);
w.close();
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
return f;
}
大功告成,打完收工,尼玛,花了我一周时间搞定,特别是改模版真烦人,一丢丢的样式都要改。
五。总结:
需要注意的细节挺多的,刚开始做的时候肯定很多坑,数据不能为空,初始化模版方法,数据转换等。
六:案例demo程序下载
freemarker模板导出word循环图片表格源码和详细教程-Java文档类资源-CSDN下载
请看使用必看