POI使用--循环word模版填入对应数据、图片(包含嵌套循环)

1.目录结构

2.引入依赖

        <!--poi-tl word支持-->
        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.10.2</version>
        </dependency>

3.准备word模版数据

健康宝-同时空协查函模板.docx 内容如下

{ {?section1}}

北京市疾病预防控制中心关于

新型冠状病毒感染病例

接触者的协查函

健康宝注册人员:姓名:{ {healthKitGeneratorName}} ,电话:{ {phone}} ,身份证号:{ {icNumber}} ,二维码见附图,谢谢!

望尽早协助为盼。

疾病预防控制中心

附图:健康宝扫码登记二维码

{ {?qrCode}}

{ {@pictures}}

{ {/qrCode}}

{ {/section1}}

注意点1:如果是普通文字输出在word模版上,则要用{ {变量名}}替代。如果是图片的话。要用{ {@变量名}}替代。

注意点2:遍历模版输出使用的是 区块对 标签,该标签使用格式

{ {?变量名}}

模版和数据

{ {/变量名}}

区块对标签官网地址:Poi-tl Documentation

注意点3:由于项目需求,单独一个协查函可能包含多个二维码图片信息。所以我使用了循环嵌套区块对标签,最外层section1标签是循环输出模版整个协查函模版,与HealthKitLetterInfo类对象对应。内层的qrCode标签是循环输出图片,与HealthKitLetterInfo类内的qrCode属性对应。

4.实体创建

4.1 PointPositionForm类

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class PointPositionForm {
    private List<String> healthKitScreenshots;
    private String healthKitGeneratorName;
    private String phoneNum;
    private String idNum;

}

4.2 HealthKitLetterInfo类

由于在paramMap中区块对的标签变量对应的是该类的集合。该实体内的字段属性要与word模版中变量名对应

@Data
@Builder
public class HealthKitLetterInfo {
    private String healthKitGeneratorName;
    private String phone;
    private String icNumber;
    private List<Map<String, PictureRenderData>> qrCode;
}

5.word文档输出逻辑

    public static void main(String[] args) {

        Map<String, Object> paramMap = new HashMap<>();
        
        // 创建两个有数据的实体
        List<PointPositionForm> healthKits = new ArrayList<>();
        healthKits.add(PointPositionForm.builder()
                .phoneNum("1333333333")
                .idNum("我是身份证号1")
                .healthKitGeneratorName("测试姓名1")
                .healthKitScreenshots(Arrays.asList(
                        "/Users/liangjia/Downloads/Snipaste_2022-05-18_14-25-25.png",
                        "/Users/liangjia/Downloads/测试图.png",
                        "/Users/liangjia/Downloads/Snipaste_2022-05-18_14-25-25.png"
                )).build());

        healthKits.add(PointPositionForm.builder()
                .phoneNum("18888888888")
                .idNum("我是身份证号2")
                .healthKitGeneratorName("测试姓名2")
                .healthKitScreenshots(Arrays.asList(
                        "/Users/liangjia/Downloads/测试图.png",
                        "/Users/liangjia/Downloads/Snipaste_2022-05-18_14-25-25.png"
                )).build());

        List<HealthKitLetterInfo> healthKitLetterInfos = new ArrayList<>();

        // 遍历两个实体,将数据添加到word文档模版对应的实体上
        for (PointPositionForm healthKit : healthKits) {
            HealthKitLetterInfo healthKitLetterInfo = HealthKitLetterInfo.builder()
                    .healthKitGeneratorName(healthKit.getHealthKitGeneratorName())
                    .phone(healthKit.getPhoneNum())
                    .icNumber(healthKit.getIdNum())
                    .qrCode(new ArrayList<>())
                    .build();


            // 多个健康宝二维码
            List<String> healthKitScreenshots = healthKit.getHealthKitScreenshots();
            List<Map<String, PictureRenderData>> qrCode = healthKitLetterInfo.getQrCode();
            for(String imageUrl : healthKitScreenshots){

                Map<String,PictureRenderData> map=new HashMap<>();
                map.put("pictures", new PictureRenderData(100, 120, imageUrl));
                qrCode.add(map);
            }
            healthKitLetterInfos.add(healthKitLetterInfo);
        }

        paramMap.put("section1",healthKitLetterInfos);

        // 生成文件
        Map<String, String> resultMap = createPdf(paramMap);
    }


    private static Map<String, String> createPdf(Map<String, Object> paramMap) {
        log.info("生成电子协查函参数paramMap = {}", paramMap);
        // 文件存放根目录
        String rootPath = "/Users/liangjia" + File.separator ;
        File dir = new File(rootPath);
        // 文件夹不存在则创建
        if (!dir.exists()) {
            boolean mkdir = dir.mkdir();
            if (!mkdir) {
                log.error("文件目录创建失败");
            }
        }
        String docxPath = rootPath + "健康宝-同时空协查函" + ".docx";
        String imgPath = rootPath + "image" + File.separator;
        // 获取电子协查函模板
        String path = "file-template" + File.separator + "健康宝-同时空协查函模板.docx";
        // 根据模板渲染word、并且生成pdf文件
        ClassPathResource classPathResource = new ClassPathResource(path);
        try (InputStream inputStream = classPathResource.getInputStream()) {
            if (Objects.isNull(inputStream)) {
                log.error("获取电子协查函模板失败");
            }
            // 通过协查函模板,开始生成电子协查函
            try (XWPFTemplate template = XWPFTemplate.compile(inputStream).render(paramMap);
                 OutputStream outDocx = Files.newOutputStream(Paths.get(docxPath))) {
                NiceXWPFDocument xwpfDocument = template.getXWPFDocument();

                // 输出word
                template.getXWPFDocument().write(outDocx);
            }
        } catch (Exception e) {
            log.error("创建协查函异常,异常详情:\n{}", e);
        }
        Map<String, String> map = new HashMap<>(4);
        map.put("rootPath", rootPath);
        map.put("docxPath", docxPath);
        return map;
    }

输出文件结果

猜你喜欢

转载自blog.csdn.net/liangjiabao5555/article/details/124933626