Springboot 通过Freemarker 模板引擎导出word
虽然网上很多,到处都是,但是自己做的时候还是会遇到很多问题,特意笔记一下。
现在来说功能和开发步骤;
需求
导出如下图所示的word文档
这个word文档也算不上太复杂,主要有几个特点:文本字段(string)、列表字段(list)
开发步骤
先来处理word模板文件
准备模板Word
把word模板文件另存为,如下图
把保存后的模板的后缀名改成.ftl ,如下图
word 模板处理的差不多了,在来处理代码
a. 添加freemarker模板
<!--添加freemarker模板-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.27-incubating</version>
</dependency>
b. 把刚才修改成.ftl后缀名的模板文件直接拷贝到项目当中,在点击打开编辑,如下图
————————————————————-修改模板字段————————————
—————————————–后台模板字段——————————
———————————–修改list表格模板————————————
——————————后台字段模板—————————————–
注意:上面的后台字段模板是为了让大家知道页面绑定什么样的字段,后台就绑定什么样的字段或是集合
${wsl.stepNo!''}
还有就是这种写法!”是为了判断是否为空,如果为空不处理就会报错,所以绑定的字段后面加!”
其实在一开始创建word模板的时候就可以添加${String}绑定的字段,但是修改后缀名ftl后里面的内容回乱, 还要在页面中在修改,所以建议最后在修改ftl模板。
c. 开始写代码了,放在你想要调用的控制器下面就行:
//word生成和下载 工作票生成 cwm add 2018-5-2
@RequestMapping("downLoad")
public ResponseEntity<InputStreamResource> dowmload(Integer id) throws Exception {
////获取跟目录
File path = new File(ResourceUtils.getURL("classpath:").getPath());
//如果上传目录为/downfile,则可以如下获取:
File downfile = new File(path.getAbsolutePath(),"downfile/");
if(!downfile.exists()) downfile.mkdirs();
//文件保存路径
String filePath = URLDecoder.decode( downfile.getPath(), "UTF-8");//"D:\\baidupan";
//文件唯一名称
String ticketName="工作票"+ new SimpleDateFormat("yyyyMMddhhmmss").format(new Date())+ ".doc";
String fileOnlyName =URLDecoder.decode( ticketName,"UTF-8");
String modelName="freemarker.ftl";
File staticPath = new File(path.getAbsolutePath(),"templates/workticket/");
String sourePath=URLDecoder.decode(staticPath.getPath(),"UTF-8");
//准备数据 这里的数据是为生成word模板准备的数据,调用下面的方法生成的数据
Map<String,Object> dataMap= getTicketAllData(id);
/** 生成word */
if(WordHelper.wordutil(dataMap, modelName, filePath,sourePath,fileOnlyName))
{
FileSystemResource file = new FileSystemResource(filePath + File.separator + fileOnlyName);
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
String downfilename=new String(file.getFilename().getBytes("GB2312"), "ISO_8859_1");
headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"",downfilename ));
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
return ResponseEntity
.ok()
.headers(headers)
.contentLength(file.contentLength())
.contentType(MediaType.parseMediaType("application/octet-stream"))
.body(new InputStreamResource(file.getInputStream()));
}else
{
throw new Exception(URLDecoder.decode("生成word文档失败!","UTF-8"));
}
}
d. 这里是准备的数据
/**
* cwm add 2018-5-5
* 根据工作票id来获取工作票导出信息
* @param id
* @return
*/
private Map<String,Object> getTicketAllData(Integer id)
{
Map<String,Object> dataMap=new HashMap<>();
WorkTicketModel workTicketModel = optWorkTicketService.getWorkTicketModel(id);
if(workTicketModel!=null)
{
//工作票
WorkTicketVM workTicketVM=workTicketModel.getWorkTicketVM();
if(workTicketVM!=null)
{
dataMap.put("repair_company",workTicketVM.getRepair_company()==null?"":workTicketVM.getRepair_company());
dataMap.put("wt_no",workTicketVM.getWt_no()==null?"":workTicketVM.getWt_no());
dataMap.put("team_leader",workTicketVM.getTeam_leader()==null?"":workTicketVM.getTeam_leader());
dataMap.put("change_no",workTicketVM.getChange_no()==null?"":workTicketVM.getChange_no());
dataMap.put("team_member",workTicketVM.getTeam_member()==null?"":workTicketVM.getTeam_member());
dataMap.put("work_content",workTicketVM.getWork_content()==null?"":workTicketVM.getWork_content());
dataMap.put("start_time",workTicketVM.getStart_time()==null?"":workTicketVM.getStart_time());
dataMap.put("end_time",workTicketVM.getEnd_time()==null?"":workTicketVM.getEnd_time());
dataMap.put("hot_tip",workTicketVM.getHot_tip()==null?"":workTicketVM.getHot_tip());
dataMap.put("licensor_time_end",workTicketVM.getLicensor_time_start()==null?"":workTicketVM.getLicensor_time_start());//没有
dataMap.put("issuer_id",workTicketVM.getIssuer_name()==null?"":workTicketVM.getIssuer_name());//没有
dataMap.put("licensor_time_start",workTicketVM.getLicensor_time_start()==null?"":workTicketVM.getLicensor_time_start());//没有
dataMap.put("team_leader",workTicketVM.getTeam_member()==null?"":workTicketVM.getTeam_member());
//dataMap.put("team_member",workTicketVM.getTeam_member());
dataMap.put("delay_leader","");//延期负责人没有
dataMap.put("delay_licensor_id","");//延期许可人 没有
dataMap.put("re_delay_leader","");//再次延期负责人 没有
dataMap.put("re_delay_licensor_id","");//再次延期许可人 没有
dataMap.put("finish_time","");//全部工作结束时间没有
dataMap.put("remark","");//备注没有
}
//隔离措施
WorkInsulateVM workInsulateVM= workTicketModel.getWorkInsulate();
if(workInsulateVM!=null)
{
dataMap.put("isolationNo",workInsulateVM.getIsolationNo()==null?"":workInsulateVM.getIsolationNo());
dataMap.put("description",workInsulateVM.getDescription()==null?"":workInsulateVM.getDescription());
dataMap.put("condition",workInsulateVM.getCondition()==null?"":workInsulateVM.getCondition());
dataMap.put("approverPerson",workInsulateVM.getApproverPerson()==null?"":workInsulateVM.getApproverPerson());
dataMap.put("markCardNo",workInsulateVM.getMarkCardNo()==null?"":workInsulateVM.getMarkCardNo());
}
//安全措施
List<WorkSecurityVM> workSecurityList= workTicketModel.getWorkSecurityList();
if(workSecurityList!=null)
{
dataMap.put("workSecurityList",workSecurityList);
}
//危险点预控措施
List<WorkPreventVM> workPreventList = workTicketModel.getWorkPreventList();
if(workPreventList!=null)
{
dataMap.put("workPreventList",workPreventList);
}
}
return dataMap;
}
e. 导出word的帮助类:
public class WordHelper {
/**
* 生成word文件
* @param dataMap word中需要展示的动态数据,用map集合来保存
* @param templateName word模板名称,例如:test.ftl
* @param filePath 文件生成的目标路径,例如:D:/wordFile/
* @param sourePath word模板路径
* @param fileName 生成的文件名称,例如:test.doc
*/
@SuppressWarnings("unchecked")
public static boolean wordutil(Map dataMap, String templateName, String filePath,String sourePath, String fileName)
{
try {
//创建配置实例
Configuration configuration = new Configuration();
//设置编码
configuration.setDefaultEncoding("utf-8");
//ftl模板文件
//configuration.setClassForTemplateLoading(WordHelper.class,"/");
//指定路径的第二种方式,我的路径是C:/a.ftl
configuration.setDirectoryForTemplateLoading(new File(sourePath));
//获取模板
Template template = configuration.getTemplate(templateName);
/*以下是两种指定ftl文件所在目录路径的方式, 注意这两种方式都是
* 指定ftl文件所在目录的路径,而不是ftl文件的路径
*/
//指定路径的第一种方式(根据某个类的相对路径指定)
//configuration.setClassForTemplateLoading(this.getClass(),"");
//输出文件
File outFile = new File(filePath+ File.separator+fileName);
//如果输出目标文件夹不存在,则创建
if (!outFile.getParentFile().exists()){
outFile.getParentFile().mkdirs();
}
//将模板和数据模型合并生成文件
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"utf-8"));
//生成文件
template.process(dataMap, out);
//关闭流
out.flush();
out.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
欢迎大家批评和指导
每个人的背后都会有心酸,每个人的故事都有泪流。自己的路总归要自己走。困了,让自己睡一觉,累了,给自己一个拥抱;失败了,跌倒了,有人帮扶,一定要感恩,无人支持,也绝不气馁,随时记得给自己一份坚强,继续前行。
美好一天从“坚强”开始!
共同学习,共同进步,技术交流群:210470210