Generate Word Documents from Templates in Java with POI and POI‑TL

This article walks through using the Apache POI and POI‑TL libraries to render Word (.docx) files from custom templates, covering version compatibility, template syntax, data model definitions, and step‑by‑step code examples for text, images, tables, and charts.

The Dominant Programmer
The Dominant Programmer
The Dominant Programmer
Generate Word Documents from Templates in Java with POI and POI‑TL

Scenario

A Java back‑end needs to generate Word documents from a template, filling text, images, tables, and charts based on data from a database or other sources.

poi‑tl Overview

poi‑tl (POI Template Language) is an open‑source Word template engine (Apache License 2.0) that renders tags in a .docx template into text, images, tables, lists, charts, conditional blocks, loops, hyperlinks, bookmarks, code highlights, Markdown, etc. Repository: https://github.com/Sayi/poi-tl. Documentation: https://deepoove.com/poi-tl/.

Version Compatibility

The latest poi‑tl version is 1.12.2 , which requires Apache POI 5.2.2 or newer. If the project uses an older POI version (e.g., 4.1.2), the compatible poi‑tl version is 1.8.2 . Example Maven dependencies:

<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-ooxml</artifactId>
  <version>4.1.2</version>
</dependency>

<dependency>
  <groupId>com.deepoove</groupId>
  <artifactId>poi-tl</artifactId>
  <version>1.8.2</version>
</dependency>

Quick Start

Create a .docx template and insert a placeholder such as {{title}} where the text should appear.

Rendering method:

public static void render(Map<String, Object> map) {
    XWPFTemplate template = XWPFTemplate.compile("D://test//temp.docx").render(map);
    try (FileOutputStream out = new FileOutputStream("D://test//output.docx")) {
        template.write(out);
    } catch (IOException e) {
        e.printStackTrace();
    }
    template.close();
}

Invoke the method:

render(new HashMap<String, Object>() {{
    put("title", "Hi, poi‑tl Word template engine");
}});

Data Model and Text Tag Attributes

Supported value types: String – plain text. TextRenderData – styled text. HyperLinkTextRenderData – hyperlink text.

Any object – its toString() result is used.

Example of styled text creation:

data.put("author", new TextRenderData("000000", "Sayi"));
data.put("author2", new TextRenderData("霸道的程序猿",
    StyleBuilder.newBuilder()
        .buildColor("00FF00")
        .buildStrike()
        .buildBold()
        .buildItalic()
        .buildUnderLine()
        .buildFontFamily("微软雅黑")
        .buildFontSize(12)
        .build()));

Image Tag

Image tags start with @. The following code demonstrates three ways to provide image data:

HashMap<String, Object> data = new HashMap<>();
// Local file
data.put("local", new PictureRenderData(80, 100, "D://test//test.png"));
// Byte stream
try {
    data.put("localbyte", new PictureRenderData(80, 100, ".png", new FileInputStream("D://test//test.png")));
} catch (FileNotFoundException e) { e.printStackTrace(); }
// Network image (may affect performance)
data.put("urlpicture", new PictureRenderData(50, 50, ".png", BytePictureUtils.getUrlBufferedImage("http://deepoove.com/images/icecream.png")));
// BufferedImage from Java
try {
    BufferedImage img = ImageIO.read(new File("D://test//test.png"));
    data.put("bufferimage", new PictureRenderData(80, 100, ".png", img));
} catch (IOException e) { e.printStackTrace(); }
render(data);

Table Tag

Table tags start with #. Example constructing a table with a header and two rows:

HashMap<String, Object> data = new HashMap<>();
RowRenderData header = RowRenderData.build(
    new TextRenderData("000000", "姓名"),
    new TextRenderData("000000", "学历"));
RowRenderData row0 = RowRenderData.build("张三", "研究生");
RowRenderData row1 = RowRenderData.build("李四", "博士");
data.put("table", new MiniTableRenderData(header, Arrays.asList(row0, row1)));
render(data);

Chart Tag (Pie Chart Example)

Insert a chart placeholder such as {{pieChart}} in the template. Build the chart data in Java:

HashMap<String, Object> data = new HashMap<>();
ChartSingleSeriesRenderData pie = new ChartSingleSeriesRenderData();
pie.setChartTitle("ChartTitle");
pie.setCategories(new String[]{"俄罗斯", "加拿大", "美国", "中国"});
pie.setSeriesData(new SeriesRenderData("countries", new Integer[]{17098242, 9984670, 9826675, 9596961}));
data.put("pieChart", pie);
render(data);

Other chart types are documented on the official site.

Additional Resources

Full feature list, template samples, and code examples are available at https://deepoove.com/poi-tl/.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaTemplate EnginePOIWordDocument GenerationPOI‑TL
The Dominant Programmer
Written by

The Dominant Programmer

Resources and tutorials for programmers' advanced learning journey. Advanced tracks in Java, Python, and C#. Blog: https://blog.csdn.net/badao_liumang_qizhi

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.