一、需要jar
<!-- https://mvnrepository.com/artifact/org.freemarker/freemarker -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
二、java代码
@Override
public Boolean downWorkStudy(HttpServletResponse response,String fileDate,Integer reportDateId) {
Map data = new HashMap();
QueryWrapper<SysDictItem> wrapper = new QueryWrapper<>();
wrapper.eq("type","dept_type");
wrapper.eq("del_flag",0);
List<SysDictItem> deptTypeList = sysDictItemService.list(wrapper);
int i = 1;
for(SysDictItem sysDictItem : deptTypeList) {
List<Map> listDept = new ArrayList<>();
Set<String> deptSet = new HashSet<>();
List<WorkReportInfoVO> workReportInfoList = baseMapper.selectWorkReportInfoList("", sysDictItem.getValue(),reportDateId);
for (WorkReportInfoVO workReportInfoVO : workReportInfoList) {
deptSet.add(workReportInfoVO.getDeptId());
}
List<Map> listContent = new ArrayList<>();
for (String deptid : deptSet) {
Map<String, Object> deptMap = new HashMap<>();
QueryWrapper<SysDept> wrapper1 = new QueryWrapper<>();
wrapper1.eq("id", deptid);
wrapper1.eq("del_flag", 0);
SysDept sysDept = sysDeptService.getOne(wrapper1);
if (null != sysDept) {
deptMap.put("dept_name", sysDept.getName());
} else {
deptMap.put("dept_name", deptid);
}
deptMap.put("id", i);
listDept.add(deptMap);
data.put("listDept"+i, listDept);
List<WorkReportInfoVO> deptList = baseMapper.selectWorkReportInfoList(deptid,sysDictItem.getValue(),reportDateId);
for (int j = 0; j < deptList.size(); j++) {
Map<String, Object> contentMap = new HashMap<>();
contentMap.put("teacher_name", deptList.get(j).getTeacherName());
contentMap.put("dept_name", deptList.get(j).getDeptName());
listContent.add(contentMap);
}
}
data.put("listContent" + i, listContent);
i++;
}
data.put("fileDate",fileDate);
logger.info("doc============="+JSONUtil.toJsonStr(data));
try {
//Configuration 用于读取ftl文件
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
/**
* 以下是两种指定ftl文件所在目录路径的方式,注意这两种方式都是
* 指定ftl文件所在目录的路径,而不是ftl文件的路径
*/
//指定路径的第一种方式(根据某个类的相对路径指定)
// configuration.setClassForTemplateLoading(this.getClass(), "");
//指定路径的第二种方式,我的路径是C:/a.ftl
configuration.setDirectoryForTemplateLoading(new File("D:/"));
//输出文档路径及名称
File outFile = new File("D:/【文档】"+fileDate+".doc");
//以utf-8的编码读取ftl文件
Template template = configuration.getTemplate("word.ftl", "utf-8");
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"), 10240);
template.process(data, out);
out.close();
//转换成前端可以导出
FileUtils.downloadFile(response,"D:/","【文档】"+fileDate+".doc");
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
三、ftl模板(这里是将html文件更改后缀名ftl)
<!DOCTYPE html>
<html lang="en" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml"
xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文档(${fileDate})</title>
<style>
body{
font-size: 14px!important;
}
@page Section1 {
mso-header-margin: .59in;
mso-footer-margin:.69in;
mso-header: h1;
mso-footer: f1;
}
div.Section1 {
page: Section1;
margin-bottom: 0;
}
p.MsoFooter, div.MsoFooter {
margin: 0in;
/*margin-bottom: .0001pt;*/
mso-pagination: widow-orphan;
tab-stops: center 3.0in right 6.0in;
}
.ta-c{
text-align: center;
}
.fs21{
font-size: 21px!important;
}
.fs16{
font-size: 16px!important;
}
.fwn{
font-weight: normal;
}
.fwb{
font-weight: bold;
}
.bg-yellow{
background-color: #fff723;
}
</style>
</head>
<body style="font-family:'仿宋',serif; font-size:14px;">
<div>
</div>
<div class="Section1">
<div style="mso-element:header" id="h1">
<p class="MsoHeader" style="font-family:'仿宋',serif;font-size:12px; text-align: right; border-bottom: 1px solid #000">文档(${fileDate})</p>
</div>
<div style="mso-element:footer" id="f1">
<p class="MsoFooter" style="font-size:12px;text-align: right">
<span>
<span style='mso-field-code:" PAGE "'></span>
/
<span style='mso-field-code:" NUMPAGES "'></span>
</span>
<span style="font-size:12.0pt;"> </span>
<span>页脚</span>
</p>
</div>
<div class="fs16">
<h4 class="ta-c" style="font-size:21px;">一、文档(${fileDate})</h4>
<div>
<h2 style="font-size:16px;"><span style="background-color: #fff723;">第一部分</span></h2>
<#list listDept1! as item1>
<h3 style="font-size:16px;">${item1.dept_name!}</h3>
<#list listContent1! as content1>
<#if content1.dept_name! == item1.dept_name!>
<p style="margin-bottom:0px"><b>${content1.teacher_name!} </b>${content1.post_name!}</p>
<p style="margin-top:0;text-indent:21.0pt">${content1.work_study!}</p>
</#if>
</#list>
</#list>
</div>
<div>
<h2 style="font-size:16px;"><span style="background-color: #fff723;">第二部分 </span></h2>
<#list listDept2! as item2>
<h3 style="font-size:16px;">${item2.dept_name!}</h3>
<#list listContent2! as content2>
<#if content2.dept_name! == item2.dept_name!>
<p style="margin-bottom:0px"><b>${content2.teacher_name!} </b>${content2.post_name!}</p>
<p style="margin-top:0;text-indent:21.0pt">${content2.work_study!}</p>
</#if>
</#list>
</#list>
</div>
<div>
<h2 style="font-size:16px;"><span style="background-color: #fff723;">第三部分</span></h2>
<#list listDept3! as item3>
<h3 style="font-size:16px;">${item3.dept_name!}</h3>
<#list listContent3! as content3>
<#if content3.dept_name! == item3.dept_name!>
<p style="margin-bottom:0px"><b>${content3.teacher_name!} </b>${content3.post_name!}</p>
<p style="margin-top:0;text-indent:21.0pt">${content3.work_study!}</p>
</#if>
</#list>
</#list>
</div>
</div>
<div class="fs16">
<h1 class="ta-c" style="font-size:14px;">二、文档(${fileDate})</h1>
<div class="fs16">
<h2 style="font-size:16px;"><span style="background-color: #fff723;">第一部分 </span></h2>
<#list listDept1! as item1>
<h3 style="font-size:16px;">${item1.dept_name!}</h3>
<#list listContent1! as content1>
<#if content1.dept_name! == item1.dept_name!>
<#if content1.support_need! != '无' && content1.support_need! != '暂无' && content1.support_need! != 'NA' && content1.support_need! != '暂无。' && content1.support_need! != '-'>
<p style="margin-bottom:0px"><b>${content1.teacher_name!} </b>${content1.post_name!}</p>
<p style="margin-top:0;text-indent:21.0pt">${content1.support_need!}</p>
</#if>
</#if>
</#list>
</#list>
</div>
<div>
<h2 style="font-size:16px;"><span style="background-color: #fff723;">第二部分</span></h2>
<#list listDept2! as item2>
<h3 style="font-size:16px;">${item2.dept_name!}</h3>
<#list listContent2! as content2>
<#if content2.dept_name! == item2.dept_name!>
<#if content2.support_need! != '无' && content2.support_need! != '暂无' && content2.support_need! != 'NA' && content2.support_need! != '暂无。' && content2.support_need! != '-'>
<p style="margin-bottom:0px"><b>${content2.teacher_name!} </b>${content2.post_name!}</p>
<p style="margin-top:0;text-indent:21.0pt">${content2.support_need!}</p>
</#if>
</#if>
</#list>
</#list>
</div>
<div>
<h2 style="font-size:16px;"><span style="background-color: #fff723;">第三部分</span></h2>
<#list listDept3! as item3>
<h3 style="font-size:16px;">${item3.dept_name!}</h3>
<#list listContent3! as content3>
<#if content3.dept_name! == item3.dept_name!>
<#if content3.support_need! != '无' && content3.support_need! != '暂无' && content3.support_need! != 'NA' && content3.support_need! != '暂无。' && content3.support_need! != '-'>
<p style="margin-bottom:0px"><b>${content3.teacher_name!} </b>${content3.post_name!}</p>
<p style="margin-top:0;text-indent:21.0pt">${content3.support_need!}</p>
</#if>
</#if>
</#list>
</#list>
</div>
</div>
</div>
</body>
</html>
注意:
1、其实java中template.process(data, out)获取的data就是一个json,然后在ftl中 可以通过这个key获取对应的值:
如${listDept1}。
2、用html转换ftl,因为html比较好渲染word的格式。