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