一、添加maven依赖,导入FreeMarker所需要的jar包
org.freemarker
freemarker
2.3.20
二、定义word模板文件
三、修改模板xml文件
把刚刚制作的word文件另存为xml文件
修改这个xml文件,开发工具我用的idea,我是把这个xml文件放在项目中,Ctrl+Alt+L进行格式化,这样文件内容看起来结构比较清晰,方便修改,你也可以使用其他xml编辑器等等
如XML 在线格式化 | 菜鸟工具
把文档内容中的动态数据,换成freemarker的标识。其实就是Map
房间使用,场地使用,用餐情况是需要循环遍历的,在这里可以循环遍历list,list中存储的都是Map数据,然后再一一取出,并且根据便利的条数进行动态扩展.
<#setting classic_compatible=true>
K
K
1
2021-12-28T06:39:00Z
2021-12-30T06:25:07Z
432000
1
0
0
0
0
0
14
2052-11.1.0.11194
43DEF8E5B112462190ED0F6108B223F8
后勤保障需求单(CQ21070028)
一、基本信息
培训委托单位名称:
${confirmName}
班次类型
${type}
报道时间
${beginDate}
离院时间
${endDate}
学员人数
${trueNum}
学员集中接站时间
${checkOutStartDate}
学员集中退房时间
${checkOutEndDate}
教学助理姓名
${teachAssistant}
教学助理电话
${phone}
具体情况
1.房间使用情况:
房间类型
房间数量
备注
<#list detailMaps as detailMaps>
${detailMaps.dormType}
${detailMaps.dormNum}
${detailMaps.remarks}
#list>
其他要求: ${accommodationRequirements}
2.教学场地使用情况:
日期及时间
地点
备注
<#list scheduleCourseDetailMaps as scheduleCourseDetailMaps>
${scheduleCourseDetailMaps.courseDate} ~ ${scheduleCourseDetailMaps.courseBeginTime} - ${scheduleCourseDetailMaps.courseDate} ~ ${scheduleCourseDetailMaps.courseEndTime}
${scheduleCourseDetailMaps.classroom}
${scheduleCourseDetailMaps.remark}
#list>
其他情况: ${uenueRequirements}
3.用餐情况
日期
时间
地点
用餐形式
人数
标准
备注
<#list detailMealMaps as detailMealMaps>
${detailMealMaps.startDate} - ${detailMealMaps.endDate}
${detailMealMaps.startTime} - ${detailMealMaps.endTime}
${detailMealMaps.dinningPoint}
${detailMealMaps.haveMealsForm}
${detailMealMaps.number}
${detailMealMaps.haveMealsStandard}
<#--
${detailMealMaps.remarks}
-->
${detailMealMaps.remarks}
#list>
单独餐饮信息:
餐饮其他要求:
${mealRequirements}
特殊情况说明
${hqConfirmExplain}
联系人姓名: ${userName}
联系电话: ${phone}
邮箱: ${email}
上方特别注意:循环遍历
特别注意:因为导入为空时会报错,所以在xml文件加上<#setting classic_compatible=true>就不会报错了
因为转换成xml文件可能会导致${}不会识别,所以就在转换完xml文件后在去写${}就可能会避免不识别的情况
实现代码:
package com.sinosoft.springbootplus.demandConfirm.application.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sinosoft.springbootplus.demandConfirm.application.service.HqDemandConfirmExportService;
import com.sinosoft.springbootplus.demandConfirm.domain.entity.HqConfirmExplain;
import com.sinosoft.springbootplus.demandConfirm.domain.entity.HqDemandConfirm;
import com.sinosoft.springbootplus.demandConfirm.domain.entity.HqDormUseInfo;
import com.sinosoft.springbootplus.demandConfirm.domain.entity.HqMealSituation;
import com.sinosoft.springbootplus.demandConfirm.domain.mapper.HqConfirmExplainMapper;
import com.sinosoft.springbootplus.demandConfirm.domain.mapper.HqDemandConfirmMapper;
import com.sinosoft.springbootplus.demandConfirm.domain.mapper.HqDormUseInfoMapper;
import com.sinosoft.springbootplus.demandConfirm.domain.mapper.HqMealSituationMapper;
import com.sinosoft.springbootplus.mybatis.service.impl.BaseServiceImpl;
import com.sinosoft.springbootplus.project.service.JwBjBaseInfoApiService;
import com.sinosoft.springbootplus.project.vo.JwBjBaseInfohqfwVo;
import com.sinosoft.springbootplus.schedule.service.JwPtkScheduleCourseDetailByClassIdApiService;
import com.sinosoft.springbootplus.schedule.vo.JwPtkScheduleCourseDetailByClassId;
import com.sinosoft.springbootplus.util.UUIDUtil;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
/**
*
* 后勤需求确认单导出 服务实现类
*
*
* @author 李佳锴
* @since 2021-12-29
*/
@Service
@Slf4j
public class HqDemandConfirmExportServiceImpl extends BaseServiceImpl implements HqDemandConfirmExportService {
private HqDemandConfirmMapper hqDemandConfirmMapper;
private HqDormUseInfoMapper hqDormUseInfoMapper;
private HqMealSituationMapper hqMealSituationMapper;
private HqConfirmExplainMapper hqConfirmExplainMapper;
private JwBjBaseInfoApiService jwBjBaseInfoApiService;
private JwPtkScheduleCourseDetailByClassIdApiService jwPtkScheduleCourseDetailByClassIdApiService;
HqDemandConfirmExportServiceImpl(HqDemandConfirmMapper hqDemandConfirmMapper, JwPtkScheduleCourseDetailByClassIdApiService jwPtkScheduleCourseDetailByClassIdApiService,HqDormUseInfoMapper hqDormUseInfoMapper,HqMealSituationMapper hqMealSituationMapper,HqConfirmExplainMapper hqConfirmExplainMapper,JwBjBaseInfoApiService jwBjBaseInfoApiService){
this.hqDemandConfirmMapper =hqDemandConfirmMapper;
this.jwPtkScheduleCourseDetailByClassIdApiService=jwPtkScheduleCourseDetailByClassIdApiService;
this.hqDormUseInfoMapper =hqDormUseInfoMapper;
this.hqMealSituationMapper = hqMealSituationMapper;
this.hqConfirmExplainMapper =hqConfirmExplainMapper;
this.jwBjBaseInfoApiService = jwBjBaseInfoApiService;
}
private static final String ENCODING = "UTF-8";
private static Configuration cfg = new Configuration();
//初始化cfg
static {
//设置模板所在文件夹
cfg.setClassForTemplateLoading(HqDemandConfirmExportServiceImpl.class, "/templates");
// setEncoding这个方法一定要设置国家及其编码,不然在ftl中的中文在生成html后会变成乱码
cfg.setEncoding(Locale.getDefault(), ENCODING);
// 设置对象的包装器
cfg.setObjectWrapper(new DefaultObjectWrapper());
// 设置异常处理器,这样的话就可以${a.b.c.d}即使没有属性也不会出错
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
}
//获取模板对象
public static Template getTemplate(String templateFileName) throws IOException {
return cfg.getTemplate(templateFileName, ENCODING);
}
/**
* 据数据及模板生成文件
* @param data Map的数据结果集
* @param templateFileName ftl模版文件名
* @param outFilePath 生成文件名称(可带路径)
*/
public static File crateFile(Map data, String templateFileName, String outFilePath) {
Writer out = null;
File outFile = new File(outFilePath);
try {
// 获取模板,并设置编码方式,这个编码必须要与页面中的编码格式一致
Template template = getTemplate(templateFileName);
if (!outFile.getParentFile().exists()) {
outFile.getParentFile().mkdirs();
}
out = new OutputStreamWriter(new FileOutputStream(outFile), ENCODING);
// 处理模版
template.process(data, out);
out.flush();
log.info("由模板文件" + templateFileName + "生成" + outFilePath + "成功.");
} catch (Exception e) {
log.error("由模板文件" + templateFileName + "生成" + outFilePath + "出错");
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
log.error("关闭Write对象出错", e);
e.printStackTrace();
}
}
return outFile;
}
@Override
public void getHqDemandConfirmPageList(Long confirmId) throws Exception {
//查询后勤房间使用情况
QueryWrapper queryWrapper = Wrappers.query()
.eq("confirm_id",confirmId);
List roomInfos = hqDormUseInfoMapper.selectList(queryWrapper);
//查询保障单信息
QueryWrapper queryWrapperDemandConfirms = Wrappers.query()
.eq("id",confirmId);
HqDemandConfirm hqDemandConfirms = hqDemandConfirmMapper.selectOne(queryWrapperDemandConfirms);
//查询用餐情况信息
QueryWrapper queryWrapperMeal = Wrappers.query()
.eq("confirm_id",confirmId);
List hqMealSituationList = hqMealSituationMapper.selectList(queryWrapperMeal);
//查询特殊情况信息
QueryWrapper queryWrapperExplain = Wrappers.query()
.eq("confirm_id",confirmId);
HqConfirmExplain hqConfirmExplain = hqConfirmExplainMapper.selectOne(queryWrapperExplain);
//用于存储所有数据
Map data = new HashMap<>();
//查询基本信息
//设置日期格式
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
//首先查询出confirmId找出它的classId
Long classId = hqDemandConfirms.getClassId();
//根据classId查询它的班级基本信息
JwBjBaseInfohqfwVo baseInfo = jwBjBaseInfoApiService.getBaseInfo(classId);
data.put("confirmName",hqDemandConfirms.getConfirmName());
if (baseInfo.getType() == 0){
data.put("type","主题班次");
}else if (baseInfo.getType() == 1){
data.put("type","党日活动");
}else {
data.put("type","高校");
}
//修改时间格式为(yyyy-MM-dd)
String beginDate = sdf2.format(baseInfo.getBeginDate());
data.put("beginDate",beginDate);
//修改时间格式为(yyyy-MM-dd)
String endDate = sdf2.format(baseInfo.getEndDate());
data.put("endDate",endDate);
if (baseInfo.getTrueNum() == null){
data.put("trueNum",0);
}else {
data.put("trueNum",baseInfo.getTrueNum());
}
//修改时间格式为(yyyy-MM-dd)
String checkOutStartDate = sdf2.format(hqDemandConfirms.getCheckOutStartDate());
data.put("checkOutStartDate",checkOutStartDate);
//修改时间格式为(yyyy-MM-dd)
String checkOutEndDate = sdf2.format(hqDemandConfirms.getCheckOutEndDate());
data.put("checkOutEndDate",checkOutEndDate);
data.put("teachAssistant",baseInfo.getTeachAssistant());
data.put("phone",hqDemandConfirms.getPhone());
//获取场地所有信息
List hqDemandConfirmExport = hqDemandConfirmMapper.getHqDemandConfirmExport(queryWrapperDemandConfirms);
//获取培训单所有班级Id
List list = new ArrayList<>();
for (HqDemandConfirm demandConfirm : hqDemandConfirmExport) {
list.add(demandConfirm.getClassId());
}
//用于存储遍历出来的所有数据
List
//用于存储所有数据
Map
凡是需要遍历的都得用这个,先存储到map里面,然存储到list集合里,最后存储到总集合里面
//用于存储遍历出来的所有数据
List
//根据班级Id获取场地所有信息
Map