【Java 】根据 poi-tl 制作模板导出word

本文介绍了如何使用poi-tl库在Word报告中嵌入HTML、Markdown内容,以及处理文本、表格、图片和动态数据的示例,包括Maven依赖配置、SpringEL表达式的应用和实体类的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

由于近期对于客户需求,需要在word报表中,展示html以及markdown的需求,
用了poi-tl更加方便点,接下来是具体介绍一下
针对普通的word中文本、表格、图片以及特殊html等,操作过程。

开源链接

poi-tl 文档链接: poi-tl

Maven依赖

		<dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.10.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>5.0.0</version>
        </dependency>
        
        <!--SpringEL表达式-->
        <!-- <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>5.3.18</version>
        </dependency> -->

【注】:SpringEL表达式很关键 ,在word模板中可以使用Spring语言

模板设置

  1. word中文本的动态生成
  2. 表格操作
  3. 图片
  4. html
    在这里插入图片描述

代码示例

import cn.hutool.core.util.RandomUtil;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.*;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.deepoove.poi.policy.ListRenderPolicy;
import com.deepoove.poi.policy.PictureRenderPolicy;
import com.deepoove.poi.policy.TableRenderPolicy;
import entity.UserInfo;
import org.ddr.poi.html.HtmlRenderPolicy;

import java.io.*;
import java.util.*;

public class POITLExportUtil {

    public static void main(String[] args) throws IOException {
        // 模板路径
        InputStream inputStream = new FileInputStream("F:\\templates\\poi_tl_export.docx");
        // 输出模板路径
        String saveFilePath = "F:\\templates\\poi_tl_export\\out"+ RandomUtil.randomString(5) + ".docx";
        if(!new File(saveFilePath).getParentFile().exists()){
            new File(saveFilePath).getParentFile().mkdir();
        }
        // 文本数据
        Map<String, Object> data = new HashMap<>();
        // 图片数据
        Map<String, Object> picsMap = new HashMap<>();
        // 表格
        LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
        // html
        HtmlRenderPolicy htmlRenderPolicy = new HtmlRenderPolicy();
        // 用户信息
        List<UserInfo> userInfoList = new ArrayList<>();
        UserInfo u1 = new UserInfo();
        u1.setNo(1); u1.setName("张三");  u1.setAge(23);
        userInfoList.add(u1);
        UserInfo u2 = new UserInfo();
        u2.setNo(2); u2.setName("李四");  u2.setAge(24);
        userInfoList.add(u2);
        // 动态表格
        Tables.TableBuilder tableBuilder = Tables.of().center();// 宽度自适应
        // 下面这个是根据自己表格的列数,计算大概需要多少宽度
//        Tables.TableBuilder tableBuilder = Tables.of().width(23.26f, new double[]{23.26/14, 23.26*4/14, 23.26*4/14, 23.26*2/14,23.26*2/14,23.26*2/14});
        TableRenderData tableRenderData = tableBuilder.create();// 表格创建
        // 表格行设置
        // 设置两个表头
        RowRenderData row0 = Rows.of("序号","姓名", "年龄", "成绩","成绩","成绩").textColor("FFFFFF").bgColor("4472C4").center().create();
        RowRenderData row2 = Rows.of("","", "", "语文","数学","英语").textColor("FFFFFF").bgColor("4472C4").center().create();
        tableRenderData.addRow(row0);
        tableRenderData.addRow(row2);
        RowRenderData row3 = Rows.of("1","张三", "15", "80","95","78").center().create();
        RowRenderData row4 = Rows.of("2","李四", "14", "92","96","81").center().create();
        tableRenderData.addRow(row3);
        tableRenderData.addRow(row4);
        // 设置表头合并规则
        MergeCellRule.MergeCellRuleBuilder mergeCellRuleBuilder = MergeCellRule.builder();
        mergeCellRuleBuilder.map(MergeCellRule.Grid.of(0, 3), MergeCellRule.Grid.of(0, 5));
        mergeCellRuleBuilder.map(MergeCellRule.Grid.of(0, 0), MergeCellRule.Grid.of(1, 0));
        mergeCellRuleBuilder.map(MergeCellRule.Grid.of(0, 1), MergeCellRule.Grid.of(1, 1));
        mergeCellRuleBuilder.map(MergeCellRule.Grid.of(0, 2), MergeCellRule.Grid.of(1, 2));
        tableBuilder.mergeRule(mergeCellRuleBuilder.build());
        data.put("table1",tableRenderData);

        // 填充字段
        data.put("content1","Hi, poi-tl Word模板引擎");// 文本内容
        // 图片
        data.put("imge1", Pictures.ofStream(new FileInputStream("F:\\test_path\\poiTl\\image\\cat001.jpg")).size(80, 80).create());
        // 表格列表数据
        data.put("userList",userInfoList);
        // 一个占位多张图片展示
        String path = "F:\\test_path\\poiTl\\image\\cat001.jpg,F:\\test_path\\poiTl\\image\\cat002.jpg";
        String[] pList = path.split(",");
        String imgList = "";
        for(int i=0;i<pList.length;i++){
            imgList = imgList + "{{@imgList_" + i +"}}";
            picsMap.put("imgList_"+i,Pictures.ofStream(new FileInputStream(pList[i])).size(80, 80).create());
        }
        data.put("imgList",imgList);// 多个图片设置成文本,文本设置图片格式,通过二次渲染将图片填充
        // 设置字段属性()
        Configure builder = Configure.builder()
                .bind("content1", htmlRenderPolicy) // 若该字段属于特殊文本可以加下标识
                .bind("imge1",new PictureRenderPolicy()) // 图片
                .bind("userList", policy) // 表格集合数组
                .bind("table1",new TableRenderPolicy()) // 表格
                .useSpringEL(true)
                .build();

        //生成文件
        XWPFTemplate.compile(inputStream, builder)
                .render(data)
                .writeToFile(saveFilePath);

        // 动态多个图片插入
        XWPFTemplate.compile(saveFilePath).render(picsMap).writeToFile(saveFilePath);
    }

}

用到的实体类

import lombok.Data;

@Data
public class UserInfo {

    // 序号
    private Integer no;

    // 姓名
    private String name;

    // 年龄
    private Integer age;
}

结果展示

在这里插入图片描述

Java中,利用POI-TL(Apache POI的Template Library)模板引擎来处理Word文档并嵌入多重循环是很常见的需求。POI-TL提供了一种方便的方式来操作Microsoft Office文件,包括Word。下面是一个基本步骤,展示如何在模板中添加多重循环: 1. **引入依赖**: 首先,你需要在项目中引入`org.apache.poi.xwpf.usermodel`和`org.apache.poi.xwpf.template`库,这两个包包含处理Word模板和文档的功能。 2. **创建模板**: 使用`XWPFDocument.create()`方法创建一个新的Word模板文档,并加载预定义的模板文件。你可以从本地读取模板文件,或者直接作为字符串内容传递。 ```java XWPFDocument template = new XWPFDocument(new FileInputStream("template.docx")); ``` 3. **设置循环变量**: 设定一个或多个需要迭代的数据集合,比如List、Map等,用于填充模板中的循环部分。例如,假设你有一个学生列表: ```java List<Student> students = ...; // 学生对象列表 ``` 4. **遍历并插入数据**: 使用`XWPFParagraph`的`addRun()`方法,在模板的每个循环位置插入新的文本行。对于每个学生,你可以创建一个新的段落或者追加到现有段落。 ```java for (Student student : students) { XWPFParagraph para = template.addNewParagraph(); para.addRun().append(student.getName()); // 如果有其他信息,如成绩,可以继续添加到run中 } ``` 5. **替换占位符**: 在模板中可能有一些特殊的标签(通常是特殊字符或标记),表示需要动态填充的部分。使用`XWPFTextRun.replaceText()`方法将这些占位符替换为实际数据。 6. **保存结果**: 最后,将修改后的模板保存为一个新的Word文档。 ```java OutputStream outputStream = new FileOutputStream("output.docx"); template.write(outputStream); outputStream.close(); ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值