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

Posted lllllLiangjia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
    

输出文件结果

以上是关于POI使用--循环word模版填入对应数据图片(包含嵌套循环)的主要内容,如果未能解决你的问题,请参考以下文章

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

使用poi根据模版生成word文档,支持插入数据和图片

poi根据模版生成多页word,并压缩下载

POI根据模板导出word文件,以及word转PDF,PDF转图片再插入PDF中(防止PDF被修改)

POI根据模板导出word文件,以及word转PDF,PDF转图片再插入PDF中(防止PDF被修改)

java 调用word模板实现循环套打生成word文档