利用Poi-tl实现word模版动态导出

97 阅读2分钟

话不多说,先上需求,本次导出的word涉及到借据信息的动态取值,可能会涉及到多个借据,本人之前做这种类型的需求一般使用毕升office服务,但本次服务的客户没用采用,看了许多方法最后采用简单的Poi-tl image.png

需要满足:
-   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/