话不多说,先上需求,本次导出的word涉及到借据信息的动态取值,可能会涉及到多个借据,本人之前做这种类型的需求一般使用毕升office服务,但本次服务的客户没用采用,看了许多方法最后采用简单的Poi-tl
需要满足:
- JDK1.8+
- Apache POI5.2.2+
首先需要导入依赖
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.10.0</version>
</dependency>
具体的业务代码:
/**
* 获取xwpf模板
*
* @param businessNo 项目编号
* @param entity 实体
* @param inputStream 输入流
* @param isOverdue 是否已逾期
* @param riskManagerUserList 风险经理用户列表
* @return {@link XWPFTemplate }
*/
private XWPFTemplate getXwpfTemplate(String businessNo, CustWarningArtificialInfoEntity entity, InputStream inputStream, String isOverdue, List<SysUserEntity> riskManagerUserList) {
// 为借据号的显示绑定行循环
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
// 将promissory设置为行循环绑定的数据源的key,即key是promissory的value会在模板中的{{promissory}}处进行解析
Configure configure = Configure.builder().bind("promissory", policy).build();
// 读取模板、数据并渲染
return XWPFTemplate.compile(inputStream, configure).render(
// 创建一个map并设置为只读map
Collections.unmodifiableMap(new HashMap<String, Object>() {
{
// 设置普通文本的值
put("examineDate", StrUtil.isNotBlank(entity.getExamineDate()) ? entity.getExamineDate() : "");//检查时间
put("borrower", StrUtil.isNotBlank(entity.getEnterpriseName()) ? entity.getEnterpriseName() : "");//借款人名称
put("loanBalance", Objects.nonNull(entity.getLoanBalance()) ? entity.getLoanBalance() : "");//贷款余额
put("deptName", StrUtil.isBlank(entity.getDeptId()) ? " " : sysDeptService.getDeptByDeptId(entity.getDeptId()).getName()); //部门
put("organizerName", StrUtil.isNotBlank(entity.getOrganizerName()) ? entity.getOrganizerName() : "");//主办客户经理
put("assistedOrganizerName", StrUtil.isNotBlank(entity.getAssistedOrganizerName()) ? entity.getAssistedOrganizerName() : "");//协办客户经理
//非逾期报告
if (StrUtil.equals(isOverdue, "0")) {
put("details", StrUtil.isNotBlank(entity.getDetails()) ? entity.getDetails() : ""); //本次收集资料明细
put("registeredAddress", StrUtil.isNotBlank(entity.getRegisteredAddress()) ? entity.getRegisteredAddress() : "");//注册地址
put("address", StrUtil.isNotBlank(entity.getAddress()) ? entity.getAddress() : ""); //实际经营地址
put("contents", StrUtil.isNotBlank(entity.getContents()) ? entity.getContents() : "");//检查内容及结论
put("mortgages", bizReturnVisitInfoService.getCollateralAddressByDataId(entity.getId()));//抵押情况
put("mortgagor", bizReturnVisitInfoService.getCollateralOwnerByDataId(entity.getId()));//抵押人
put("guarantor", bizReturnVisitInfoService.getGuarantorNameByDataId(entity.getId()));//保证人情况
// 设置取得方式: 0:自有;1:租赁 2:其他:
String getType = entity.getGetType();//
List<String> list = Arrays.asList("0", "1","2");
for (int index = 0; index < list.size(); index++) {
if (list.get(index).equals(getType)) {
put("box" + index, "☑");
} else {
put("box" + index, "□");
}
}
}
//逾期报告
if (StrUtil.equals(isOverdue, "1")) {
put("overdueReason", entity.getIsOverdue());//逾期原因
put("nextWork", entity.getNextWork());//下一步工作
put("principalOverdueTime", StrUtil.isNotBlank(entity.getPrincipalOverdueTime()) ? entity.getPrincipalOverdueTime() : "");//本金逾期时间
put("interestOverdueTime", StrUtil.isNotBlank(entity.getInterestOverdueTime()) ? entity.getInterestOverdueTime() : "");//利息逾期时间
}
// 设置选择框-检查方式 0-现场 1-非现场
String examineType = entity.getExamineType();//
List<String> list = Arrays.asList("0", "1");
for (int index = 0; index < list.size(); index++) {
if (list.get(index).equals(examineType)) {
put("checkBox" + index, "☑");
} else {
put("checkBox" + index, "□");
}
}
// 借据信息在表格里循环
List<NotPawnVO> forms = bizReturnVisitInfoService.getNotePawnByDataId(entity.getId());
for (int i = 0; i < forms.size(); i++) {
put("promissoryNo" + i, forms.get(i).getPromissoryNo());
put("loanTerm" + i, forms.get(i).getLoanTerm()+"天");
}
// 借据信息
put("promissory", forms);
HashMap<String, String> options = getOptions(entity, riskManagerUserList);
putAll(options);
}
})
);
}
/**
* 单个导出模版文件
*
* @param map 入参
* @param response 响应
*/
@Override
public void exportPostSingleCastFiles(Map<String, Object> map, HttpServletResponse response) {
String id = MapUtil.getStr(map, "id");
Assert.notBlank(id, () -> new RRException("id不能为空"));
File tempDir = null;
try {
// 创建临时目录
tempDir = new File(FileUtil.getTemporaryFilePath(), UUID.fastUUID().toString());
if (!tempDir.exists()) {
tempDir.mkdirs();
}
File finalTempDir = tempDir;
CustWarningArtificialInfoEntity entity = custWarningArtificialInfoDao.selectById(id);
Assert.isTrue(Objects.nonNull(entity), () -> new RRException("id对应的数据不存在"));
//兼容旧数据
String isOverdue = CharSequenceUtil.isNotEmpty(entity.getIsOverdue()) ? entity.getIsOverdue() : "0";
InputStream inputStream = CustWarningArtificialInfoServiceImpl.class
.getClassLoader()
.getResourceAsStream(StrUtil.equals(isOverdue, "0") ? "normalCasting.docx" : "abNormalCasting.docx");
Assert.isTrue(inputStream != null, () -> new RRException("模板文件不存在!"));
List<SysUserEntity> riskManagerUserList = sysUserService.getRiskManagerUser();
String randomNumbers = RandomUtil.randomNumbers(6);
XWPFTemplate template = this.getXwpfTemplate(entity.getBusinessNo(), entity, inputStream, isOverdue, riskManagerUserList);
// 生成word保存在指定目录
String path = Paths.get(finalTempDir.getPath(), randomNumbers + ".docx").toString();
template.writeToFile(path);
template.close();
this.convertWordToPdf(path);
FileUtil.download(path.replace(".docx", ".pdf"), response, "投后回访报告.pdf");
} catch (IOException e) {
log.error("下载投后报告存在问题", e);
throw new RRException("下载投后报告存在问题,请联系管理员");
} finally {
cn.hutool.core.io.FileUtil.del(tempDir);
}
}
上述方法可能涉及到了具体的业务代码,大体的流程是生成XWPFTemplate,生成word,按照需求然后再转化为pdf。 更多Poi-tl使用可以参考 deepoove.com/poi-tl/