Quickly Generate Word Reports with SpringBoot and POI‑TL

This article shows how to use SpringBoot together with the POI‑TL template engine to create Word reports that embed text, images, tables and charts, providing a step‑by‑step guide, code snippets and a reusable utility class for rapid document generation.

Programmer XiaoFu
Programmer XiaoFu
Programmer XiaoFu
Quickly Generate Word Reports with SpringBoot and POI‑TL

1. Poi‑tl Overview

Poi‑tl is a lightweight, cross‑platform Java library built on Apache POI. It uses a Freemarker‑like syntax to replace placeholders in a Word template and provides extensibility through a plugin mechanism.

2. Common Tags

2.1 Text

Format: {{var}}

Example:

put("name", "Sayi");
put("author", new TextRenderData("000000", "Sayi"));
// Hyperlink
put("link", new HyperLinkTextRenderData("website", "http://deepoove.com"));

2.2 Image

Format: starts with @, {{@var}}

Example:

// Local image
put("local", new PictureRenderData(80, 100, "./sayi.png"));
// Image stream
put("localbyte", new PictureRenderData(80, 100, ".png", new FileInputStream("./logo.png")));
// Network image (beware of latency)
put("urlpicture", new PictureRenderData(50, 50, ".png", BytePictureUtils.getUrlBufferedImage("http://deepoove.com/images/icecream.png")));

2.3 Table

Format: starts with #, {{#var}}

Data model is illustrated in the accompanying image.

2.4 List

Format: starts with *, {{*var}}

Supported list styles include decimal, roman numerals, bullets, etc.

FMT_DECIMAL // 1. 2. 3.
FMT_DECIMAL_PARENTHESES // 1) 2) 3)
FMT_BULLET // ● ● ●
FMT_LOWER_ROMAN // i ii iii

2.5 Single‑Series Chart

Used for charts that display a single data series (e.g., pie chart). The placeholder follows the same {{val}} syntax.

2.6 Multi‑Series Chart

Used for combined charts such as bar‑line mixes. The format is identical to the single‑series case.

3. Code Encapsulation

The tag handling is wrapped in a set of classes:

public enum WordContentTypeEnum { TEXT, PICTURE, TABLE, LIST, CHART; }

public class LabelData { private String labelName; private WordContentTypeEnum typeEnum; }

public interface GenerateWord { Object generateWord(LabelData data); }

public class GenerateWordFactory {
    private static final Map<WordContentTypeEnum, GenerateWord> TYPE_BACK_DATA = new HashMap<>();
    public static void register(WordContentTypeEnum type, GenerateWord impl) { TYPE_BACK_DATA.put(type, impl); }
    public static GenerateWord getBackData(WordContentTypeEnum type) { return TYPE_BACK_DATA.get(type); }
}

Specific implementations ( TextGenerateWord, PictureGenerateWord, TableGenerateWord, ListGenerateWord, ChartGenerateWord) are annotated with @Component and register themselves in GenerateWordFactory via @PostConstruct.

3.5 Chart Generation

The chart data model distinguishes single‑series ( ChartSingleSeriesRenderData) and multi‑series ( ChartMultiSeriesRenderData) and uses CharCombinationType to indicate the combination mode.

4. Testing

4.1 Template File

The Word template is placed under resources/static/template/demo_template.docx.

4.2 Assemble Data

private static final String TEMPLATE_PATH = "static/template/demo_template.docx";

List<LabelData> generates = new ArrayList<>();
// Text
TextContentData title = new TextContentData();
title.setContent("2022 Monthly Report").setLabelName("title").setTypeEnum(WordContentTypeEnum.TEXT);
generates.add(title);

// Styled text
TextContentData styled = new TextContentData();
styled.setRenderData(new TextRenderData("cc0000", "Styled content"))
      .setLabelName("typeContent").setTypeEnum(WordContentTypeEnum.TEXT);
generates.add(styled);

// Image
PictureContentData pic = new PictureContentData();
pic.setWidth(200).setHeight(160).setPicType(PicTypeEnum.JPG)
   .setFile(new File("D:/down/java.jpg"))
   .setLabelName("picture").setTypeEnum(WordContentTypeEnum.PICTURE);
generates.add(pic);

// Table
TableSeriesRenderData table = new TableSeriesRenderData();
TextRenderData[] header = { new TextRenderData("Class"), new TextRenderData("Rank") };
List<TextRenderData[]> rows = Arrays.asList(
    new TextRenderData[]{ new TextRenderData("Science 1"), new TextRenderData("1") },
    new TextRenderData[]{ new TextRenderData("Kindergarten 3"), new TextRenderData("6") }
);
table.setHeader(header).setContents(rows).setLabelName("showTable").setTypeEnum(WordContentTypeEnum.TABLE);
generates.add(table);

// List
ListRenderData list = new ListRenderData();
list.setList(Arrays.asList(new TextRenderData("Item 1"), new TextRenderData("Item 2"), new TextRenderData("Item 3")))
    .setPair(NumbericRenderData.FMT_LOWER_ROMAN)
    .setLabelName("numList").setTypeEnum(WordContentTypeEnum.LIST);
generates.add(list);

// Charts (line, bar, pie, etc.) – examples omitted for brevity but follow the same pattern using ChartSeriesRenderData.

OperateWordManage.generateWordContent(templateFile, "D:/down/output.docx", generates);

4.3 Result

The generated Word document contains all placeholders replaced with the supplied text, images, tables, lists and charts, demonstrating that the POI‑TL based utility can quickly produce complex reports.

Source code is available at:

https://github.com/lovejiashn/generate_report.git

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.

JavaSpringBootTemplate EngineWordPOI‑TLReport Generation
Programmer XiaoFu
Written by

Programmer XiaoFu

xiaofucode.com – a programmer learning guide driven by the pursuit of profit

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.