Java使用poi-tl库操作wold文档的方法

 更新时间:2025年11月26日 11:48:51   作者:布Coder  
java项目实际开发中经常会遇到制作word表单且表格数据行循环功能,这篇文章主要介绍了Java使用poi-tl库操作wold文档的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

poi-tl 是一个基于Apache POI的Word模板引擎,也是一个免费开源的Java类库,

适用范围:

在线文档生成、合同签订、信息替换方面具有很大优势、采用 标签-替换的实现策略,简单易上手、避免实际业务中的重复开发. 业务与设计解藕.

开始操作

引入 poi-tl 项目

        <poi-version>5.4.0</poi-version>
        
        -- poi 项目依赖

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>${poi-version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>${poi-version}</version>
        </dependency>

        -- poi-tl 项目依赖
        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.12.2</version>
        </dependency>

本讲介绍模版生成(poi - tl支持无模版生成)

读取模版文件、并且定义结果输出

        XWPFTemplate
                .compile("模版文档.docx")
                .render(map)
                .writeAndClose(new FileOutputStream("01.docx"));
  • XWPFTemplate :  模版操作类
    • compile : 模版文档
    • render : 数据
    • writeAndClose : 结果输出

普通图文本替换 (文档内容 {{key}})

模版文件

代码

        HashMap<String, Object> renderMap = new HashMap<>();

        renderMap.put("text","我是被替换的内容");

        XWPFTemplate
                .compile("空白文档.docx")
                .render(renderMap).
                writeAndClose(new FileOutputStream("01.docx"));

输出文件

列表内容生成 {{#key}}

模版

代码实现

        HashMap<String, Object> renderMap = new HashMap<>();

        renderMap.put("text", "我是被替换的内容");

        HashMap<String, Object> ones = new HashMap<>();

        ones.put("name", "981129-1");
        ones.put("date", new Date());

        ArrayList<Object> list = new ArrayList<>();
        list.add(ones);
        list.add(ones);
        list.add(ones);
        list.add(ones);

        renderMap.put("list", list);

        // 表格循环插件
        LoopRowTableRenderPolicy rowTableRenderPolicy = new LoopRowTableRenderPolicy();
        Configure configure = Configure.builder()
                .bind("list", rowTableRenderPolicy)
                .build();


        XWPFTemplate
                .compile("空白文档.docx", configure)
                .render(renderMap).
                writeAndClose(new FileOutputStream("01.docx"));

复杂结构列表内容生成 (循环生成普通文本 + 列表)

自定义实现(代码)

package com.bu.poi.world.plugns;

import com.bu.poi.world.VsEty;
import com.bu.poi.world.domain.DtEntity;
import com.bu.poi.world.domain.ObjEty;
import com.deepoove.poi.policy.AbstractRenderPolicy;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.template.run.RunTemplate;
import com.deepoove.poi.xwpf.BodyContainer;
import com.deepoove.poi.xwpf.BodyContainerFactory;
import com.deepoove.poi.xwpf.XWPFParagraphWrapper;
import org.apache.poi.xwpf.usermodel.*;

import java.util.List;

/**
 * @author haizhuangbu
 * @date 03 8月 2025 06:46
 * @mark CustomTableRenderPolicy
 */
public class CustomTableRenderPolicy extends AbstractRenderPolicy<VsEty> {

    @Override
    protected void afterRender(RenderContext<VsEty> context) {
        clearPlaceholder(context, true);
    }

    @Override
    public void doRender(RenderContext<VsEty> renderContext) {

        // 编辑行
        XWPFRun run = renderContext.getRun();


        RunTemplate runTemplate = (RunTemplate) renderContext.getEleTemplate();


        // 数据
        VsEty data = renderContext.getData();

        BodyContainer bodyContainer = BodyContainerFactory.getBodyContainer(run);


        List<DtEntity> list = data.getList();
        for (DtEntity dtEntity : list) {

            XWPFRun nvRun = createRun(runTemplate, (XWPFParagraph) run.getParent());

            nvRun.setText(dtEntity.getTitle() + "\n");

            bodyContainer.insertNewParagraph(nvRun);
            nvRun.addBreak();

            XWPFRun nvRun1 = createRun(runTemplate, (XWPFParagraph) nvRun.getParent());

            nvRun1.setText(dtEntity.getIdx() + "\n");
            bodyContainer.insertNewParagraph(nvRun1);
            nvRun1.addBreak();


            List<ObjEty> objEtyList = dtEntity.getList();

            for (ObjEty objEty : objEtyList) {
//                createRun(run);
//                XWPFRun tbRun = createRun(runTemplate, (XWPFParagraph) nvRun1.getParent());
                XWPFRun tbRun = createRun(run);
                XWPFTable table = bodyContainer.insertNewTable(tbRun, 0, 0);
                createRow(table, objEty);
                table.setWidth(8000);

            }


        }


    }

    private XWPFRun createRun(RunTemplate runTemplate, XWPFParagraph parent) {
        XWPFParagraphWrapper paragraphWrapper = new XWPFParagraphWrapper(parent);
        return paragraphWrapper.insertNewRun(runTemplate.getRunPos());

    }

    public void createRow(XWPFTable table, ObjEty objEty) {

        table.setInsideHBorder(XWPFTable.XWPFBorderType.SINGLE, 10, 2, "E8E8E8");
        table.setLeftBorder(XWPFTable.XWPFBorderType.SINGLE, 10, 2, "E8E8E8");
        table.setRightBorder(XWPFTable.XWPFBorderType.SINGLE, 10, 2, "E8E8E8");
        table.setTopBorder(XWPFTable.XWPFBorderType.SINGLE, 10, 2, "E8E8E8");
        table.setBottomBorder(XWPFTable.XWPFBorderType.SINGLE, 10, 2, "E8E8E8");
        XWPFTableRow r1 = table.getRow(0);


        XWPFTableCell left = r1.getCell(0);
        left.setText("姓名");


        XWPFTableCell right = r1.createCell();
        right.setText(objEty.getName());


        XWPFTableRow r2 = table.createRow();
        XWPFTableCell r2Left = r2.getCell(0);
        r2Left.setText("码值");
        XWPFTableCell r2Right = r2.getCell(1);
        r2Right.setText(objEty.getTCode());

        XWPFTableRow r3 = table.createRow();
        XWPFTableCell r3Left = r3.getCell(0);
        r3Left.setText("中文名");
        XWPFTableCell r3Right = r3.getCell(1);
        r3Right.setText(objEty.getTName());


    }


    public XWPFRun createRun(XWPFRun run) {
        XWPFDocument document = run.getDocument();
        XWPFParagraph paragraph = document.createParagraph();
        return paragraph.createRun();
    }


}
        VsEty vsEty = new VsEty();

        ArrayList<DtEntity> dtEntities = new ArrayList<>();


        DtEntity dtEntity = new DtEntity();
        dtEntity.setIdx("我是下标\n");
        dtEntity.setTitle("我是标题\n");

        List<ObjEty> objEties = new ArrayList<>();

        ObjEty objEty = new ObjEty();
        objEty.setName("name");
        objEty.setTName("name1");
        objEty.setTCode("code1");


        ObjEty objEty2 = new ObjEty();
        objEty2.setName("name");
        objEty2.setTName("name1");
        objEty2.setTCode("code1");

        objEties.add(objEty);
        objEties.add(objEty2);


        dtEntity.setList(objEties);

        dtEntities.add(dtEntity);


        vsEty.setList(dtEntities);

        renderMap.put("report", vsEty);

        CustomTableRenderPolicy customTableRenderPolicy = new CustomTableRenderPolicy();

        // 表格循环插件
        LoopRowTableRenderPolicy rowTableRenderPolicy = new LoopRowTableRenderPolicy();
        Configure configure = Configure.builder()
                .bind("list", rowTableRenderPolicy)
                .bind("report", customTableRenderPolicy)
                .build();


        XWPFTemplate
                .compile("空白文档.docx", configure)
                .render(renderMap).
                writeAndClose(new FileOutputStream("01.docx"));

模版

输出样式

官方文档地址:https://deepoove.com/poi-tl/#loop-col-table

总结

到此这篇关于Java使用poi-tl库操作wold文档方法的文章就介绍到这了,更多相关Java poi-tl操作word文档内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • feign服务端发现异常客户端处理的方法介绍

    feign服务端发现异常客户端处理的方法介绍

    这篇文章主要给大家介绍了关于feign服务端发现异常客户端处理的方法,文中通过示例代码介绍的非常详细,对大家学习或者使用feign具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-07-07
  • Mybatis的详细使用教程

    Mybatis的详细使用教程

    这篇文章主要介绍了Mybatis的详细使用教程,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-12-12
  • springboot跨域过滤器fetch react Response to preflight request doesn‘t pass access control check问题

    springboot跨域过滤器fetch react Response to p

    这篇文章主要介绍了springboot跨域过滤器fetch react Response to preflight request doesn‘t pass access control check问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • skywalking分布式服务调用链路追踪APM应用监控

    skywalking分布式服务调用链路追踪APM应用监控

    这篇文章主要为大家介绍了skywalking分布式服务调用链路追踪APM应用监控的功能使用说明,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2022-03-03
  • Java数组(Array)最全汇总(上篇)

    Java数组(Array)最全汇总(上篇)

    这篇文章主要介绍了Java数组(Array)最全汇总(上篇),本文章内容详细,通过案例可以更好的理解数组的相关知识,本模块分为了三部分,本次为上篇,需要的朋友可以参考下
    2023-01-01
  • Java实现批量操作Excel的示例详解

    Java实现批量操作Excel的示例详解

    在操作Excel的场景中,通常会有一些针对Excel的批量操作,以GcExcel为例,为大家详细介绍一下Java是如何实现批量操作Excel的,需要的可以参考一下
    2023-07-07
  • 深入理解Java编程线程池的实现原理

    深入理解Java编程线程池的实现原理

    这篇文章主要介绍了深入理解Java编程线程池的实现原理,涉及ThreadPoolExecutor类,线程池实现原理及示例等相关内容,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • 浅谈Java中的桥接方法与泛型的逆变和协变

    浅谈Java中的桥接方法与泛型的逆变和协变

    对应于Java当中,协变对应的就是<? extends XXX>,而逆变对应的就是<? super XXX>,本文详细的介绍了Java中的桥接方法与泛型的逆变和协变,感兴趣的可以了解一下
    2022-04-04
  • Java字符串中有多个分隔符的处理方式

    Java字符串中有多个分隔符的处理方式

    这篇文章主要介绍了Java字符串中有多个分隔符的处理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-05-05
  • java中文转全拼工具类分享

    java中文转全拼工具类分享

    这篇文章主要介绍了一个JAVA将汉字转换为全拼的工具类,大参考使用吧
    2014-01-01

最新评论