本期我們介紹如何使用Freemarker導出word文檔?
項目需求如下:
前些時間開發人力資源項目,項目在正式上線之後,客戶錄入的大良人員基礎信息,包括人員基礎信息,教育經歷,工作經歷,培訓經歷與家庭情況,這些數據都是使用獨立的表來存儲的,後來客戶反饋,說查看個人信息不方便,在人員調動時候還需要打印個人簡歷給領導看,特別提出導出個人簡歷功能
最後輸出效果如下:
經過考慮: 有兩種備選方案,第一種是使用itextPDF輸出PDF文檔,第二種是使用Freemarker導出word,但是在實際開發中發現,使用itextPDF在填充工作經歷等信息時候需要用到循環,而itextPDF對循環支持的不是很友好,於是果斷時候了Freemarker
使用模板引擎至少需要四步走:
1.定義模板引擎
2.創建數據模型
3.填充數據到模板中
4.輸出文檔
1.首先定義模板
1.1 創建word文檔,定義個人簡歷模板,效果如下:
1.2另存爲XML文件
使用文本編輯器打開
1.3定義插值
我們使用文本編輯器打開之後會有一些亂,可以使用代碼在線格式化工具格式化一下,地址https://tool.oschina.net/codeformat/xml
我們根據word模板搜索姓名,找到‘5’,並替換爲插值表達式
個人基礎信息全部使用以上方式替換
工作經歷教育經歷等需要使用循環:
搜索工作經歷:找到<w:tr>標籤,除標題之外只保留一個,每一個<w:tr>代表爲一行數據
注意
<#list workList as work>
</#list>
workList 是數據源,as 表示循環 work 代表每次循環的對象
教育經歷,家庭信息同理
處理完成後,修改後綴名爲.ftl,放到項目templates目錄下
2.代碼開始
2.1、引入依賴
<!--PDF常用工具類 -->
- <dependency>
- <groupId>com.itextpdf</groupId>
- <artifactId>itextpdf</artifactId>
- <version>2.3.28</version>
- </dependency>
/**
* 下載個人簡歷word文檔
* @param response
* @param userId
* @throws IOException
* @throws TemplateException
*/
@GetMapping("/parint1/{userId}")
@ResponseBody
public void print(HttpServletResponse response,@PathVariable("userId") String userId) throws IOException, Exception {
Long userId1 = Long.valueOf(userId);
HrStaffInfo staffInfo = hrStaffInfoService.selectHrStaffInfoById(userId1);
String content = exportFile(staffInfo);
InputStream inputStream = IOUtils.toInputStream(content);
ServletOutputStream out = null;
try {
//輸出文件
response.setHeader("content-type", "application/octet-stream");
response.setContentType("application/octet-stream;charset=UTF-8");
//response.setHeader("Content-Disposition", "attachment;filename=" + "aaa企業在編在職人員情況登記表bb"+".doc");
response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(staffInfo.getUserName()+"-順德區區屬國有企業在編在職人員情況登記表", "UTF-8")+ ".doc")));
out = response.getOutputStream();
byte[] buffer = new byte[1024]; // 緩衝區
int bytesToRead = -1;
// 通過循環將讀入的Word文件的內容輸出到瀏覽器中
while((bytesToRead = inputStream.read(buffer)) != -1) {
out.write(buffer, 0, bytesToRead);
}
}catch (Exception e){
log.error("導出Excel異常{}", e.getMessage());
throw new BusinessException("導出word失敗,請聯繫網站管理員!");
}finally {
out.flush();
out.close();
inputStream.close();
}
}
public String exportFile(HrStaffInfo staffInfo ) throws Exception{
HrStaffEducation education1 = new HrStaffEducation();
HrStaffWork hrStaffWork = new HrStaffWork();
HrStaffTrain hrStaffTrain = new HrStaffTrain();
HrStaffFamily hrStaffFamily = new HrStaffFamily();
education1.setStaffInfoId(staffInfo.getUserId());
hrStaffWork.setStaffInfoId(staffInfo.getUserId());
hrStaffTrain.setStaffInfoId(staffInfo.getUserId());
hrStaffFamily.setStaffInfoId(staffInfo.getUserId());
List<HrStaffEducation> educationList = educationService.selectHrStaffEducationList(education1);
SysDictData dictData2 = new SysDictData();
dictData2.setDictType("hr_staff_degree");
List<SysDictData> eduList = dictDataService.selectDictDataList(dictData2);
for (HrStaffEducation hrStaffEducation : educationList) {
String degree = hrStaffEducation.getDegree();
if(degree == null){
continue;
}
for (SysDictData dictData : eduList) {
if(degree.equals(dictData.getDictValue())){
hrStaffEducation.setDegree(dictData.getDictLabel());
continue;
}
}
continue;
}
//查詢工作經歷
List<HrStaffWork> workList = workService.selectHrStaffWorkList(hrStaffWork);
//查詢培訓經歷
List<HrStaffTrain> trainList = trainService.selectHrStaffTrainList(hrStaffTrain);
//查詢家庭情況
List<HrStaffFamily> familyList = familyService.selectHrStaffFamilyList(hrStaffFamily);
//創建配置類
Configuration configuration = new Configuration(Configuration.getVersion());
String classPath = this.getClass().getResource("/").getPath();
configuration.setDirectoryForTemplateLoading(new File(classPath+"templates/"));
//獲取模板文件
Template template = configuration.getTemplate("curriculum_vitae.ftl");
Map<String, Object> data = new HashMap<String, Object>();
Long companyId = staffInfo.getCompanyId();
String companyName = hrOrgCompanyService.selectHrOrgCompanyById(companyId).getDeptName();
data.put("companyName", companyName);
Calendar cal = Calendar.getInstance();
String model="yyyy-MM-dd"; //指定格式化的模板
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(model);
String date = simpleDateFormat.format(new Date());
String[] split = date.split("-");
data.put("year", split[0]);
data.put("month", split[1]);
data.put("day", split[2]);
//-------------------------------------------------------------
SysDictData dictData = new SysDictData();
List<SysDictData> sexList = dictDataService.selectDictDataList(dictData);
String sex = "";
String national = "";
String highestDegree = "";
String partHighestDegree = "";
// String national = "";
// String national = "";
for (SysDictData sysDictData : sexList) {
if (staffInfo.getSex()!= null && staffInfo.getSex().equals(sysDictData.getDictValue())&&"sys_user_sex".equals(sysDictData.getDictType())){
sex = sysDictData.getDictLabel();
}
if ( staffInfo.getNational()!= null && staffInfo.getNational().equals(sysDictData.getDictValue())&&"hr_staff_national".equals(sysDictData.getDictType())){
national = sysDictData.getDictLabel();
}
if (staffInfo.getHighestDegree()!= null && staffInfo.getHighestDegree().equals(sysDictData.getDictValue())&&"hr_staff_qualification".equals(sysDictData.getDictType())){
highestDegree = sysDictData.getDictLabel();
}
if (staffInfo.getPartHighestDegree() != null && staffInfo.getPartHighestDegree().equals(sysDictData.getDictValue())&&"hr_staff_qualification".equals(sysDictData.getDictType())){
partHighestDegree = sysDictData.getDictLabel();
}
}
//-------------------------------------------------------------
String deptName = hrOrgCompanyService.selectHrOrgCompanyById(staffInfo.getDeptId()).getDeptName();
//-------------------------------------------------------------
data.put("userName", staffInfo.getUserName()); //5
data.put("sex", sex); //7
data.put("bornYear", staffInfo.getBornYear()); //8
data.put("bornMonth", staffInfo.getBornMonth()); //8
data.put("nativePlace", staffInfo.getNativePlace()); //9
data.put("national", national); //10
data.put("idNumber", staffInfo.getIdNumber()); //11
data.put("partyTime", staffInfo.getPartyTime()); //12
data.put("workTime", staffInfo.getWorkTime()); //13
data.put("birthPlace", staffInfo.getBirthPlace()); //14
data.put("registeredPlace", staffInfo.getRegisteredPlace()); //15
data.put("highestDegree", highestDegree); //16
data.put("highestProfessional", staffInfo.getHighestProfessional()); //17
data.put("graduateSchool", staffInfo.getGraduateSchool()); //18
data.put("partHighestDegree", partHighestDegree); //19
data.put("partHighestProfessional", staffInfo.getPartHighestProfessional()); //20
data.put("partGraduateSchool", staffInfo.getPartGraduateSchool()); //21
data.put("professionalQualifications", staffInfo.getProfessionalQualifications()); //22
data.put("maritalStatus", staffInfo.getMaritalStatus()); //22
data.put("unitTime", staffInfo.getUnitTime()); //25
data.put("positionName", staffInfo.getPositionName()); //26
data.put("dept", deptName); //27
data.put("currentAddress", staffInfo.getCurrentAddress()); //28
data.put("phoneNumber", staffInfo.getPhonenumber()); //29
//-------------------------------------------------------------
// data.put("staffInfo",staffInfo);
//要和模板中定義的變量名保持一致
data.put("educationList",educationList);
data.put("workList",workList);
data.put("trainList",trainList);
data.put("familyList",familyList);
String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
return content;
}
定義前端接收請求:
/**
* 下載word文檔
*/
function print1() {
window.location.href = ctx + "hr/hrStaffInfo/parint1/" + userId;
}
如果你想輸出到本地
定義輸出路徑即可,其他代碼與輸出到瀏覽器保持一致
@GetMapping("/export/{userId}")
@ResponseBody
public TableDataInfo list(@PathVariable("userId") Long userId, HttpServletResponse response) throws Exception {
HrStaffInfo staffInfo = hrStaffInfoService.selectHrStaffInfoById(userId);
String content = exportFile(staffInfo);
try {
InputStream inputStream1 = IOUtils.toInputStream(content);
//定義輸出路徑即可,其他代碼與輸出到瀏覽器保持一致
FileOutputStream fileOutputStream = new FileOutputStream(new File("d:/test1.doc"));
int copy = IOUtils.copy(inputStream1, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
inputStream1.close();
} catch (Exception e) {
logger.error("下載個人檔案異常", e);
throw new BaseException("下載個人檔案異常");
}
好了今天的代碼就到這裏了,如有不明白之處歡迎留言。