最近项目里要做一个根据客户提供的word模板导出word的功能,方法有很多,比如easyPoi(对word的支持并不是很好),freeMark(太麻烦不想研究),以及poi-tl,
最后研究了半天发现也就只有poi-tl比较符合我的需求,特意记录下以防日后用到忘记了。
这是想要的word结果
这是我的word模板
代码如下:
try {DecimalFormat df = new DecimalFormat("###################.###########");SettlementResponse.All settlement = getDetails(settlementId);Map<String, Object> params = new HashMap<>();params.put("guestName", settlement.getBase().getGuestName());String visitStart = DateUtil.timestamp2String(settlement.getBase().getVisitTimeStart(),"yyyy年MM月dd日");String visitEnd = DateUtil.timestamp2String(settlement.getBase().getVisitTimeStart(),"MM月dd日");params.put("visitDate", visitStart+ "-" + visitEnd);SettlementResponse.Detail detail = settlement.getDetail();double total = 0;//住宿费列表if (MyUtil.isNotBlank(detail.getAccomResponse())){SettlementAccomResponse accomResponse = detail.getAccomResponse();Map<String,Object> accomMap = getAccomdation(accomResponse);params.put("accomList", accomMap.get("accomList"));params.put("accomOwn", accomMap.get("accomOwn"));params.put("accomTotal", accomMap.get("accomTotal"));total = total + accomResponse.getSubtotal().doubleValue();}//会场费列表List<Map<String,Object>> meetList = new ArrayList<>();if (CollectionUtil.isNotEmpty(detail.getMeetingResponseList())){Map<String,Object> meetingMap = getMeeting(detail.getMeetingResponseList());params.put("meetList", meetingMap.get("meetList"));params.put("meetTotal",meetingMap.get("meetTotal"));total = total + Double.parseDouble(meetingMap.get("meetTotal").toString());} else{meetList.add(new HashMap<String, Object>() {{put("meetTime", "");put("meetPlace", "");put("roomName", "");put("meetCost", "");}});params.put("meetList",meetList);}//餐饮费列表if (MyUtil.isNotBlank(detail.getMealsResponse())){List<SettlementMealsResponse.MealsDetail> mealsDetailList = detail.getMealsResponse().getMealsDetailList();Map<String,Object> mealsMap = getMeals(mealsDetailList);params.put("workMeal", mealsMap.get("workMeal"));params.put("dailMeal", mealsMap.get("dailMeal"));params.put("otheMeal", mealsMap.get("otheMeal"));params.put("mealsOwn", df.format(detail.getMealsResponse().getOwnExpense()));params.put("mealTotal", df.format(detail.getMealsResponse().getSubtotal()));total = total + detail.getMealsResponse().getSubtotal().doubleValue();}//其他费用列表List<Map<String,Object>> otherList = new ArrayList<Map<String,Object>>();if (CollectionUtil.isNotEmpty(detail.getOthersList())){Map<String,Object> otherMap = getOther(detail.getOthersList());params.put("otherList", otherMap.get("otherList"));params.put("otherTotal", otherMap.get("otherTotal"));total = total + Double.parseDouble(otherMap.get("otherTotal").toString());}else{otherList.add(new HashMap<String, Object>() {{put("otherRemark", "");put("otherCost", "");}});params.put("otherList", otherList);}//文印费params.put("printRemark", detail.getPrints().getDescription());params.put("printTotal", df.format(detail.getPrints().getCost()));total = total + detail.getPrints().getCost().doubleValue();params.put("total", df.format(total));//word模板地址,如果项目需要部署在linux环境中,需要以流的方式读取文件否则会读取不到InputStream resource= this.getClass().getClassLoader().getResourceAsStream("static/template/settlement.docx");//渲染表格,new HackLoopTableRenderPolicy(true)即模板标签和循环行在同一行而不是在上一行HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy(true);Configure config = Configure.builder().bind("accomList", policy).bind("meetList", policy).bind("workMeal", policy).bind("dailMeal", policy).bind("otheMeal", policy).bind("otherList", policy).build();XWPFTemplate template = pile(resource, config).render(params);String fileName = "接待任务费用结算表" + "-" + System.currentTimeMillis();ExportWordUtils.downloadWord(response, fileName, template);} catch (Exception e) {e.printStackTrace();}
public class ExportWordUtils {/*** 根据模板填充内容生成word,并下载* @param templatePath word模板文件路径* @param paramMap替换的参数集合*/public static void compileWord(HttpServletResponse response, InputStream templatePath, Map<String, Object> paramMap, String fileName) throws UnsupportedEncodingException {// 读取模板templatePath并将paramMap的内容填充进模板,即编辑模板(compile)+渲染数据(render)XWPFTemplate template = pile(templatePath).render(paramMap);downloadWord(response, fileName, template);}public static void downloadWord(HttpServletResponse response, String fileName, XWPFTemplate template) throws UnsupportedEncodingException {response.setContentType("application/octet-stream");fileName = URLEncoder.encode(fileName, "UTF-8");response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".docx");//设置生成的文件临时存放路径String rootPath="./wordTemplate";String filePath = rootPath + fileName;File newFile = new File(filePath);if(!newFile.getParentFile().exists()){newFile.getParentFile().mkdirs();}try {OutputStream out = response.getOutputStream();// 将填充之后的模板写入filePathtemplate.write(out);out.flush();out.close();template.close();} catch (Exception e) {e.printStackTrace();}}}
最后附上poi-tl的文档地址:/poi-tl/#hack-loop-table