首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >poi-tl的详细教程(动态表格、单元格合并)

poi-tl的详细教程(动态表格、单元格合并)

原创
作者头像
用户3672714
发布2025-08-13 13:55:00
发布2025-08-13 13:55:00
3.9K0
举报

1. 简介

  • poi-tl 是基于 Apache POI 的模板引擎,支持Word模板(.docx)中占位符渲染。
  • 支持动态表格渲染、图片、单元格合并、多级嵌套等高级功能。

2. 引入依赖(Maven)

代码语言:javascript
复制
<dependency>    <groupId>com.deepoove</groupId>    <artifactId>poi-tl</artifactId>    <version>1.13.1</version> <!-- 最新版本请到官网确认 --></dependency>php148 Bytes© 菜鸟-创作你的创作

3. 基础示例:动态表格渲染


3.1 准备Word模板

  • 在Word中创建表格,表格内填写占位符,格式例如:

序号

姓名

年龄

{{#employees}}

{{index}}

{{name}}

  • {{#employees}}...{{/employees}} 是循环开始和结束标记。
  • {{index}} 是循环中自动生成的索引(从1开始)。

3.2 Java代码实现动态填充表格

代码语言:javascript
复制
import com.deepoove.poi.XWPFTemplate;import com.deepoove.poi.data.*;import java.util.*;public class DynamicTableExample {    public static void main(String[] args) throws Exception {        // 模板路径        String template = "template.docx";        // 输出路径        String out = "out.docx";        // 构建数据列表        List<Map<String, Object>> employees = new ArrayList<>();        employees.add(new HashMap<String, Object>() {{            put("index", 1);            put("name", "张三");            put("age", 28);        }});        employees.add(new HashMap<String, Object>() {{            put("index", 2);            put("name", "李四");            put("age", 30);        }});        // 或使用 RenderData 和 MiniTableRenderData 更高级表格渲染(后面介绍)        // 构建渲染数据        Map<String, Object> data = new HashMap<>();        data.put("employees", employees);        // 渲染模板        XWPFTemplate templateDoc = XWPFTemplate.compile(template).render(data);        templateDoc.writeToFile(out);        templateDoc.close();    }}php1.01 KB© 菜鸟-创作你的创作

4. 动态表格高级渲染(使用 MiniTableRenderData)


4.1 准备Word模板

  • 在Word模板中写占位符:{{table}}

4.2 Java代码示例

代码语言:javascript
复制
import com.deepoove.poi.XWPFTemplate;import com.deepoove.poi.data.*;import com.deepoove.poi.policy.MiniTableRenderPolicy;import java.util.*;public class MiniTableExample {    public static void main(String[] args) throws Exception {        String template = "template.docx";        String out = "out_mini_table.docx";        // 表头        RowRenderData header = RowRenderData.build("序号", "姓名", "年龄");        // 构建数据行        List<RowRenderData> rows = new ArrayList<>();        rows.add(RowRenderData.build("1", "张三", "28"));        rows.add(RowRenderData.build("2", "李四", "30"));        // 构建表格数据        MiniTableRenderData tableData = new MiniTableRenderData(header, rows);        // 渲染数据        Map<String, Object> data = new HashMap<>();        data.put("table", tableData);        XWPFTemplate templateDoc = XWPFTemplate.compile(template).render(data);        templateDoc.writeToFile(out);        templateDoc.close();    }}php956 Bytes© 菜鸟-创作你的创作

5. 单元格合并


5.1 Word中模板准备

  • 合并的单元格在模板中先合并好,但如果需要动态控制,需通过代码处理。

5.2 使用 poi-tl 动态合并单元格

poi-tl 本身没有直接的合并API,但你可以在表格渲染完成后,使用 Apache POI 的API对目标表格单元格进行合并:

代码语言:javascript
复制
import org.apache.poi.xwpf.usermodel.*;import org.apache.poi.ss.util.CellRangeAddress;import java.io.FileOutputStream;import java.util.List;public class MergeCellExample {    public static void main(String[] args) throws Exception {        XWPFTemplate template = XWPFTemplate.compile("template.docx").render(null);        XWPFDocument doc = template.getXWPFDocument();        // 获取第一个表格        XWPFTable table = doc.getTables().get(0);        // 合并第一行第1列到第2列(水平合并)        mergeCellsHorizontal(table, 0, 0, 1);        // 合并第1列第2行到第3行(垂直合并)        mergeCellsVertically(table, 0, 1, 2);        // 输出文档        FileOutputStream out = new FileOutputStream("merged_output.docx");        doc.write(out);        out.close();        template.close();    }    // 水平合并单元格    public static void mergeCellsHorizontal(XWPFTable table, int row, int fromCell, int toCell) {        for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) {            XWPFTableCell cell = table.getRow(row).getCell(cellIndex);            if (cellIndex == fromCell) {                cell.getCTTc().addNewTcPr().addNewHMerge().setVal("restart");            } else {                cell.getCTTc().addNewTcPr().addNewHMerge().setVal("continue");            }        }    }    // 垂直合并单元格    public static void mergeCellsVertically(XWPFTable table, int col, int fromRow, int toRow) {        for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {            XWPFTableCell cell = table.getRow(rowIndex).getCell(col);            if (rowIndex == fromRow) {                cell.getCTTc().addNewTcPr().addNewVMerge().setVal("restart");            } else {                cell.getCTTc().addNewTcPr().addNewVMerge().setVal("continue");            }        }    }}php1.74 KB© 菜鸟-创作你的创作

6. 总结

功能

说明

动态表格渲染

使用循环占位符 或 MiniTableRenderData 实现

单元格合并

先渲染模板,再用Apache POI API对表格合并

推荐做法

模板设计时尽量预留合并单元格位置,代码灵活合并

明白!我帮你系统整理了一份 poi-tl全方位教程,包含:

  1. 动态表格渲染(基础循环+MiniTableRenderData)
  2. 单元格合并(水平合并+垂直合并)
  3. 复杂多级表格嵌套渲染示例
  4. poi-tl图片、条码、二维码渲染
  5. 性能优化与模板设计技巧

1. 动态表格渲染

1.1 基础循环渲染

模板示例:

代码语言:javascript
复制
| 序号 | 姓名 | 年龄 ||------|------|------|| {{#employees}} | {{index}} | {{name}} | {{age}} | {{/employees}} |php108 Bytes© 菜鸟-创作你的创作

Java示例:

代码语言:javascript
复制
List<Map<String, Object>> employees = new ArrayList<>();employees.add(new HashMap<String, Object>() {{ put("index", 1); put("name", "张三"); put("age", 28); }});employees.add(new HashMap<String, Object>() {{ put("index", 2); put("name", "李四"); put("age", 30); }});Map<String, Object> data = new HashMap<>();data.put("employees", employees);XWPFTemplate template = XWPFTemplate.compile("template.docx").render(data);template.writeToFile("output.docx");template.close();php475 Bytes© 菜鸟-创作你的创作

1.2 使用 MiniTableRenderData 渲染更复杂表格

代码语言:javascript
复制
RowRenderData header = RowRenderData.build("序号", "姓名", "年龄");List<RowRenderData> rows = Arrays.asList(    RowRenderData.build("1", "张三", "28"),    RowRenderData.build("2", "李四", "30"));MiniTableRenderData table = new MiniTableRenderData(header, rows);Map<String, Object> data = new HashMap<>();data.put("table", table);XWPFTemplate template = XWPFTemplate.compile("template.docx").render(data);template.writeToFile("output_mini_table.docx");template.close();php471 Bytes© 菜鸟-创作你的创作

2. 单元格合并

代码语言:javascript
复制
// 水平合并第0行第0到1单元格mergeCellsHorizontal(table, 0, 0, 1);// 垂直合并第0列第1到2行单元格mergeCellsVertically(table, 0, 1, 2);public static void mergeCellsHorizontal(XWPFTable table, int row, int fromCell, int toCell) {    for (int i = fromCell; i <= toCell; i++) {        XWPFTableCell cell = table.getRow(row).getCell(i);        if (i == fromCell) cell.getCTTc().addNewTcPr().addNewHMerge().setVal("restart");        else cell.getCTTc().addNewTcPr().addNewHMerge().setVal("continue");    }}public static void mergeCellsVertically(XWPFTable table, int col, int fromRow, int toRow) {    for (int i = fromRow; i <= toRow; i++) {        XWPFTableCell cell = table.getRow(i).getCell(col);        if (i == fromRow) cell.getCTTc().addNewTcPr().addNewVMerge().setVal("restart");        else cell.getCTTc().addNewTcPr().addNewVMerge().setVal("continue");    }}php856 Bytes© 菜鸟-创作你的创作

3. 复杂多级表格嵌套渲染示例

  • 可以用 Map 嵌套 List 的方式,结合 {{#xxx}}...{{/xxx}} 多层循环

模板示例:

代码语言:javascript
复制
| 序号 | 姓名 | 项目列表 ||------|------|----------|| {{#employees}} | {{index}} | {{name}} |     {{#projects}}    - {{projectName}} ({{duration}}月)    {{/projects}}  {{/employees}} |php181 Bytes© 菜鸟-创作你的创作

Java示例:

代码语言:javascript
复制
List<Map<String, Object>> employees = new ArrayList<>();Map<String, Object> emp1 = new HashMap<>();emp1.put("index", 1);emp1.put("name", "张三");emp1.put("projects", Arrays.asList(    Map.of("projectName", "项目A", "duration", 6),    Map.of("projectName", "项目B", "duration", 3)));Map<String, Object> emp2 = new HashMap<>();emp2.put("index", 2);emp2.put("name", "李四");emp2.put("projects", Arrays.asList(    Map.of("projectName", "项目C", "duration", 12)));employees.add(emp1);employees.add(emp2);Map<String, Object> data = new HashMap<>();data.put("employees", employees);XWPFTemplate template = XWPFTemplate.compile("template.docx").render(data);template.writeToFile("output_nested.docx");template.close();php725 Bytes© 菜鸟-创作你的创作

4. 图片、条码、二维码渲染

4.1 图片

代码语言:javascript
复制
PictureRenderData picture = new PictureRenderData(60, 60, "path/to/image.jpg");Map<String, Object> data = Map.of("picture", picture);XWPFTemplate template = XWPFTemplate.compile("template.docx").render(data);template.writeToFile("output_picture.docx");template.close();php274 Bytes© 菜鸟-创作你的创作

模板中使用 {{picture}} 占位符。


4.2 条码与二维码

poi-tl支持条码,示例:

代码语言:javascript
复制
BarCodeRenderData barcode = new BarCodeRenderData(BarCodeRenderData.BarCodeType.CODE128, "1234567890");QrCodeRenderData qrCode = new QrCodeRenderData("https://example.com", 100, 100);Map<String, Object> data = new HashMap<>();data.put("barcode", barcode);data.put("qrcode", qrCode);XWPFTemplate template = XWPFTemplate.compile("template.docx").render(data);template.writeToFile("output_code.docx");template.close();php424 Bytes© 菜鸟-创作你的创作

5. 性能优化与模板设计技巧

  • 模板设计
    • 尽量减少大表格单元格嵌套,简化循环层次。
    • 合理使用 MiniTableRenderData 分离复杂表格。
  • 数据准备
    • 预处理数据成适合模板结构的格式,避免运行时复杂转换。
  • 缓存模板
    • 如果多次生成相同模板,可缓存XWPFTemplate对象。
  • 避免重复IO
    • 批量生成时,减少频繁读写文件。
  • 占位符规范
    • 遵守poi-tl占位符规则,不使用保留字符。

https://www.52runoob.com/archives/5720

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 简介
  • 2. 引入依赖(Maven)
  • 3. 基础示例:动态表格渲染
    • 3.1 准备Word模板
    • 3.2 Java代码实现动态填充表格
  • 4. 动态表格高级渲染(使用 MiniTableRenderData)
    • 4.1 准备Word模板
    • 4.2 Java代码示例
  • 5. 单元格合并
    • 5.1 Word中模板准备
    • 5.2 使用 poi-tl 动态合并单元格
  • 6. 总结
  • 1. 动态表格渲染
    • 1.1 基础循环渲染
    • 1.2 使用 MiniTableRenderData 渲染更复杂表格
  • 2. 单元格合并
  • 3. 复杂多级表格嵌套渲染示例
  • 4. 图片、条码、二维码渲染
    • 4.1 图片
    • 4.2 条码与二维码
  • 5. 性能优化与模板设计技巧
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档