• poi-tl实现对Word模板中复杂表格的数据填充



    前言

    开发时, 我们有时需要进行word类型表格导出,
    而对于表格操作. 我们一般可能会倾向于使用 poi 进行操作. 但poi操作比较复杂,
    所以就在寻找一种可以快速将内容填充到表格中的工具. 而pot-tl 恰好满足了我们这一需求.

    what poi-tl

    poi-tl(poi template language)是Word模板引擎,使用Word模板和数据创建很棒的Word文档.
    在文档的任何地方做任何事情(Do Anything Anywhere)是poi-tl的星辰大海. 官方文档

    why poi-tl

    方案移植性功能性易用性
    Poi-tlJava跨平台Word模板引擎,基于Apache POI,提供更友好的API低代码,准备文档模板和数据即可
    Apache POIJava跨平台Apache项目,封装了常见的文档操作,也可以操作底层XML结构文档不全,这里有一个教程:Apache POI Word快速入门
    FreemarkerXML跨平台仅支持文本,很大的局限性不推荐,XML结构的代码几乎无法维护
    OpenOffice部署OpenOffice,移植性较差-需要了解OpenOffice的API
    HTML浏览器导出依赖浏览器的实现,移植性较差HTML不能很好的兼容Word的格式,样式糟糕-
    Jacob、winlibWindows平台-复杂,完全不推荐使用

    poi-tl是一个基于Apache POI的Word模板引擎,也是一个免费开源的Java类库,你可以非常方便的加入到你的项目中,并且拥有着让人喜悦的特性.

    Word模板引擎功能描述
    文本将标签渲染为文本
    图片将标签渲染为图片
    表格将标签渲染为表格
    列表将标签渲染为列表
    图表条形图(3D条形图)、柱形图(3D柱形图)、面积图(3D面积图)、折线图(3D折线图)、雷达图、饼图(3D饼图)、散点图等图表渲染
    If Condition判断根据条件隐藏或者显示某些文档内容(包括文本、段落、图片、表格、列表、图表等)
    Foreach Loop循环根据集合循环某些文档内容(包括文本、段落、图片、表格、列表、图表等)
    Loop表格行循环复制渲染表格的某一行
    Loop表格列循环复制渲染表格的某一列
    Loop有序列表支持有序列表的循环,同时支持多级列表
    Highlight代码高亮word中代码块高亮展示,支持26种语言和上百种着色样式
    Markdown将Markdown渲染为word文档
    Word批注完整的批注功能,创建批注、修改批注等
    Word附件Word中插入附件
    SDT内容控件内容控件内标签支持
    Textbox文本框文本框内标签支持
    图片替换将原有图片替换成另一张图片
    书签、锚点、超链接支持设置书签,文档内锚点和超链接功能
    Expression Language完全支持SpringEL表达式,可以扩展更多的表达式:OGNL, MVEL…
    样式模板即样式,同时代码也可以设置样式
    模板嵌套模板包含子模板,子模板再包含子模板
    合并Word合并Merge,也可以在指定位置进行合并
    用户自定义函数(插件)插件化设计,在文档任何位置执行函数

    注意: 只能操作.docx格式的word,不能操作.doc格式的word. 只能操作word中的表格, 不能操作Excel中的表格

    How poi-tl

    1. 版本问题

    在使用poi-tl时, 需要注意版本之间的冲突问题. 下面我们将使用1.10.x版本, 因此其他环境为: jdk1.8, poi:4.1.2

    V1.12.0版本作了一个不兼容的改动,升级的时候需要注意:

    • 重构了PictureRenderData,改为抽象类,建议使用Pictures工厂方法来创建图片数据

    2. 集成和使用

    2.1 pom文件坐标

    		
    <dependency>
        <groupId>org.apache.poigroupId>
        <artifactId>poiartifactId>
        <version>4.1.2version>
    dependency>
    <dependency>
        <groupId>org.apache.poigroupId>
        <artifactId>poi-ooxmlartifactId>
        <version>4.1.2version>
    dependency>
    <dependency>
        <groupId>org.apache.poigroupId>
        <artifactId>poi-ooxml-schemasartifactId>
        <version>4.1.2version>
    dependency>
    
    
    <dependency>
        <groupId>com.deepoovegroupId>
        <artifactId>poi-tlartifactId>
        <version>1.10.0version>
    dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    2.2 测试代码-map方式(最简单实用)
    复杂表格中, 可以使用这种方式进行依次填充

    @Test
    public void TestPoiTi() throws IOException {
        //===================使用Map的方式================================
        //创建目标文件C:\Users\Administrator\Documents
        Resource resource = new ClassPathResource("static/" + "poi_ti_test.docx");
        File sourceFile = resource.getFile();
        //构建数据
        Map<String, Object> data = new HashMap();
        data.put("name", "江江");
        data.put("dept", "重机部");
        data.put("level", "工程师");
        data.put("leader", "思必达");
        //创建输出流
        OutputStream os = new FileOutputStream("template1_out.docx");
        //最终编译渲染并输出
        XWPFTemplate.compile(sourceFile).render(data).writeAndClose(os);
        System.out.println("输出完毕");
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    创建表格模板

    填充效果

    2.3 行循环的形式
    需要在Configure对象中绑定需要循环的list对象

    //创建行循环策略
    LoopRowTableRenderPolicy rowTableRenderPolicy = new LoopRowTableRenderPolicy();
    //告诉模板引擎,要在employees做行循环,绑定行循环策略
    Configure configure = Configure.builder().bind("employees", rowTableRenderPolicy).build();
    //创建目标文件
    Resource resource = new ClassPathResource("static/" + "poi_ti_test2.docx");
    File sourceFile = resource.getFile();
    //构建数据
    Map<String, Object> data = new HashMap();
    
    //1.学生数据
    List<Employee> employees = new ArrayList<>();
    Employee e = new Employee("江江", "重机部", "工程师", "思必达");
    Employee e2 = new Employee("江江2", "重机部2", "工程师2", "思必达2");
    employees.add(e);
    employees.add(e2);
    //2.设置到students字段中
    data.put("employees", employees);
    //创建输出流
    OutputStream os = new FileOutputStream("template2_out.docx");
    //最终编译渲染并输出
    XWPFTemplate.compile(sourceFile, configure).render(data).writeAndClose(os);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    创建表格模板

    填充效果
    image-20221205141122494

    2.4 通过模板写入, 并通过浏览器或请求返回

    public void downloadDispatchList(Integer carReserveId, HttpServletResponse response) throws IOException {
        //用于填充的数据体
        CarReserveVO carReserveVO = getCarReserveVOById(carReserveId);
        org.springframework.core.io.Resource resource = new ClassPathResource("static/" + "模板文件.docx");
        File sourceFile = resource.getFile();
        //在模板文件中任意表格位置填充数据
        Map<String, Object> data = new HashMap();
        data.put("ycbm", carReserveVO.getCarUserDept());
        data.put("ycr", carReserveVO.getCarUserName());
        data.put("start_time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(carReserveVO.getBookerStartTime()));
        data.put("end_time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(carReserveVO.getBookerEndTime()));
     
        //浏览器端下载
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/msword");
        String fileName = carReserveVO.getCarUserName() + "的用车申请单" + ".docx";
        response.setHeader("Content-Disposition", "attachment;filename="
                .concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
        response.flushBuffer();
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile));
        //创建输出流
        OutputStream os = response.getOutputStream();
        //最终编译渲染并输出
        XWPFTemplate.compile(sourceFile).render(data).writeAndClose(os);
        byte[] buffer = new byte[1024];
        int i = bis.read(buffer);
        while (i != -1) {
            os.write(buffer, 0, i);
            i = bis.read(buffer);
        }
        if (bis != null) {
            bis.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    表格模板
    在这里插入图片描述
    填充效果
    在这里插入图片描述

    3. SpringEL表达式

    Spring Expression Language 是一个强大的表达式语言,支持在运行时查询和操作对象图,可作为独立组件使用,也可作为poi-tl模板上, 用于模板填充时参数的引用. 单独使用时需要引入相应的依赖:

    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-expressionartifactId>
      <version>5.3.18version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    关于SpringEL的写法可以参见官方文档,下面给出一些典型的示例

    {{name}}
    {{name.toUpperCase()}} 		类方法调用,转大写
    {{name == 'poi-tl'}} 		判断条件
    {{empty?:'这个字段为空'}}	
    {{sex ? '男' : '女'}}   	   三目运算符
    {{new java.text.SimpleDateFormat('yyyy-MM-dd HH:mm:ss').format(time)}}  类方法调用,时间格式化
    {{price/10000 + '万元'}} 		运算符
    {{dogs[0].name}} 			 数组列表使用下标访问
    {{localDate.format(T(java.time.format.DateTimeFormatter).ofPattern('yyyy年MM月dd日'))}}  使用静态类方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    总结

    根据poi-tl 可以操作含有多种类型的复杂 Word 文档, 包括:文本, 表格, 图片, 附件. markdown等.
    并且支持表格行循环, 表格列循环, 动态表格, 批注, 附件, 高亮等等.
    更多使用方式可以参照 官方文档, 或者 C站某大佬的一篇使用教程,
    后续如有其他需求我也将在本文进行持续更新. 下次见~

  • 相关阅读:
    【OpenCV实现图片以及视频的读取、显示、保存以及绘图函数】
    C# 移除链表元素
    模拟实现vue3.x中的计算属性
    【校招VIP】产品分析之活动策划宣传
    存储系统基本概念
    【蓝桥杯国赛真题24】Scratch货物运输 第十三届蓝桥杯 图形化编程scratch国赛真题和答案讲解
    使用运放产生各种波形
    DevExpress.NET 23.1.6 Crack
    2023年IB生物有什么变化?
    SpringBoot实现SSE构建实时数据单向推送
  • 原文地址:https://blog.csdn.net/qq_43371556/article/details/128180988