poi-tl 实战:一行文本实现多种样式(混合样式段落)

在使用 poi-tl 生成 Word 文档时,我们经常会遇到这样的需求:在同一行文本中,需要同时展示多种不同的样式,例如一部分文字是红色加粗,另一部分是蓝色普通字体。本文将详细介绍如何在 poi-tl 中优雅地实现这一功能。


一、问题背景

在传统的 Word 模板开发中,要实现"一行多样式"的效果,通常需要手动在 Word 中编辑,这不仅繁琐,而且难以复用。poi-tl 提供了强大的 ParagraphRenderDataTextRenderData 模型,让我们可以通过代码精确控制每一段、每一个字的样式。


二、核心原理

实现"一行多样式"的核心思路是:

  1. 段落容器 :使用 ParagraphRenderData 作为一个"容器",它代表 Word 中的一个段落。
  2. 文本片段 :在这个容器中,通过 addText() 方法添加多个 TextRenderData 对象。每个 TextRenderData 代表一段具有独立样式的文本。
  3. 自动接续 :多个 TextRenderData 片段会自动在同一行内接续显示,不会产生换行,从而实现"一行多样式"的效果。
  4. 渲染策略 :必须为 ParagraphRenderData 绑定 ParagraphRenderPolicy,否则 poi-tl 会将其当作普通对象,输出其 toString() 结果,而不是渲染成带样式的文本。

三、完整实现步骤

1. 依赖准备

确保你的项目中已经引入了 poi-tl 的依赖。以 Maven 为例:

xml 复制代码
<dependency>
    <groupId>com.deepoove</groupId>
    <artifactId>poi-tl</artifactId>
    <version>1.12.0</version> <!-- 请使用最新稳定版 -->
</dependency>

2. 构建混合样式段落

这是最核心的一步。我们使用 ParagraphsTexts 工厂类来构建数据模型。

java 复制代码
import com.deepoove.poi.data.ParagraphRenderData;
import com.deepoove.poi.data.Paragraphs;
import com.deepoove.poi.data.TextRenderData;
import com.deepoove.poi.data.Texts;

// 1. 构建混合样式的段落
ParagraphRenderData mixedStylePara = Paragraphs.of()
        // 第一部分:红色 + 加粗 + 14号字体
        .addText(Texts.of("这是第一种样式(红色加粗)")
                .color("FF0000")  // 红色(6位十六进制)
                .bold()           // 加粗
                .fontSize(14)
                .create())
        // 第二部分:蓝色 + 普通 + 12号字体(同一行接续)
        .addText(Texts.of(",这是第二种样式(蓝色普通)")
                .color("0000FF")  // 蓝色
                .fontSize(12)     // 字号可不同,仍在同一行
                .create())
        .create();

3. 配置渲染策略

在渲染模板前,必须通过 ConfigureParagraphRenderPolicy 绑定到对应的模板标签上。

java 复制代码
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.policy.ParagraphRenderPolicy;

// 2. 配置渲染策略(关键:必须绑定ParagraphRenderPolicy)
Configure config = Configure.builder()
        .bind("mixed_text", new ParagraphRenderPolicy())  // 绑定策略到标签名
        .build();

4. 准备数据并渲染

将构建好的 ParagraphRenderData 对象放入数据 Map 中,然后使用配置好的 Configure 来编译和渲染模板。

java 复制代码
import com.deepoove.poi.XWPFTemplate;
import java.util.HashMap;
import java.util.Map;

public class MixedStyleTextDemo {
    public static void main(String[] args) throws Exception {
        // ... 省略 ParagraphRenderData 和 Configure 的构建代码 ...

        // 3. 准备渲染数据
        Map<String, Object> data = new HashMap<>();
        data.put("mixed_text", mixedStylePara);  // 绑定到模板标签

        // 4. 渲染模板(假设模板文件为 template.docx,里面有 {{mixed_text}} 标签)
        XWPFTemplate template = XWPFTemplate.compile("template.docx", config)
                .render(data);

        // 5. 输出生成的文档
        template.writeToFile("output.docx");
        template.close();

        System.out.println("文档生成成功!");
    }
}

5. 模板文件配置

在你的 Word 模板(template.docx)中,只需要在你希望显示混合样式文本的位置,插入一个简单的标签即可:

复制代码
{{mixed_text}}

注意:标签所在位置的行样式(如行距、对齐方式)会被保留,而文本的具体样式(颜色、字体、大小)则以你在代码中设置的为准。


四、完整代码

java 复制代码
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.ParagraphRenderData;
import com.deepoove.poi.data.Paragraphs;
import com.deepoove.poi.data.Texts;
import com.deepoove.poi.policy.ParagraphRenderPolicy;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * poi-tl 一行文本实现多种样式示例
 * 功能:生成包含混合样式文本的 Word 文档
 */
public class PoiTlMixedStyleDemo {

    public static void main(String[] args) {
        // 1. 构建混合样式段落(核心:同一行多个样式)
        ParagraphRenderData mixedStyleParagraph = buildMixedStyleParagraph();

        // 2. 准备渲染数据
        Map<String, Object> renderData = new HashMap<>();
        renderData.put("mixed_text", mixedStyleParagraph);

        // 3. 配置渲染策略(必须绑定ParagraphRenderPolicy)
        Configure configure = Configure.builder()
                .bind("mixed_text", new ParagraphRenderPolicy())
                .build();

        // 4. 渲染模板并生成文档
        try {
            // 替换为你的模板文件路径(模板中只需包含 {{mixed_text}} 标签)
            String templatePath = "template.docx";
            // 生成的文档输出路径
            String outputPath = "output_mixed_style.docx";

            // 编译模板 → 渲染数据 → 输出文档
            XWPFTemplate template = XWPFTemplate.compile(templatePath, configure)
                    .render(renderData);

            // 写入文件
            template.write(new FileOutputStream(outputPath));
            // 关闭资源
            template.close();

            System.out.println("文档生成成功!输出路径:" + outputPath);
        } catch (IOException e) {
            System.err.println("文档生成失败:" + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 构建混合样式的段落(一行包含多种样式文本)
     * @return 混合样式段落对象
     */
    private static ParagraphRenderData buildMixedStyleParagraph() {
        return Paragraphs.of()
                // 第一段:红色 + 加粗 + 14号字体
                .addText(Texts.of("【重要提示】")
                        .color("FF0000")    // 红色(6位十六进制,无需#)
                        .bold()             // 加粗
                        .fontSize(14)       // 字号
                        .create())
                // 第二段:黑色 + 普通 + 12号字体
                .addText(Texts.of("本次操作将修改核心配置,")
                        .color("000000")    // 黑色
                        .fontSize(12)
                        .create())
                // 第三段:蓝色 + 斜体 + 12号字体 + 下划线
                .addText(Texts.of("请确认后再执行")
                        .color("0000FF")    // 蓝色
                        .italic()           // 斜体
                        .underline()        // 下划线
                        .fontSize(12)
                        .create())
                .create();
    }
}

五、常见问题与避坑指南

  1. 样式不生效,输出 ParagraphRenderData[contents=...]

    • 原因 :最常见的原因是没有为标签绑定 ParagraphRenderPolicy
    • 解决 :检查 Configure 配置,确保 bind("标签名", new ParagraphRenderPolicy()) 已正确执行。
  2. 文本换行

    • 原因 :如果每个 TextRenderData 都单独创建了一个 ParagraphRenderData,它们就会各自成段。
    • 解决 :确保所有样式片段都添加到同一个 ParagraphRenderData 对象中。
  3. 颜色不显示

    • 原因:颜色值格式不正确。
    • 解决 :使用 6 位十六进制字符串,如 "FF0000",不要带 # 号。
  4. *ParagraphRenderPolicy和普通的可以共用

    • 一个模板方法中即使用了ParagraphRenderPolicy,依然可以使用普通的文本填充

六、总结

通过 ParagraphRenderData 组合多个 TextRenderData 是 poi-tl 实现"一行多样式"的官方推荐方案。它不仅灵活强大,而且代码结构清晰,易于维护。只要记住**"一个段落容器,多个文本片段,必须绑定渲染策略"**这三个关键点,就能轻松应对各种复杂的文本样式需求。

相关推荐
寻寻觅觅☆8 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
l1t8 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
赶路人儿9 小时前
Jsoniter(java版本)使用介绍
java·开发语言
ceclar1239 小时前
C++使用format
开发语言·c++·算法
码说AI10 小时前
python快速绘制走势图对比曲线
开发语言·python
Gofarlic_OMS10 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
星空下的月光影子10 小时前
易语言开发从入门到精通:补充篇·网络爬虫与自动化采集分析系统深度实战·HTTP/HTTPS请求·HTML/JSON解析·反爬策略·电商价格监控·新闻资讯采集
开发语言
老约家的可汗10 小时前
初识C++
开发语言·c++
wait_luky10 小时前
python作业3
开发语言·python
消失的旧时光-194310 小时前
第十九课:为什么要引入消息队列?——异步系统设计思想
java·开发语言