<dependency> <groupId>com.deepoove</groupId> <artifactId>poi-tl</artifactId> <version>1.13.1</version> <!-- 最新版本请到官网确认 --></dependency>php148 Bytes© 菜鸟-创作你的创作序号 | 姓名 | 年龄 |
|---|---|---|
{{#employees}} | {{index}} | {{name}} |
{{#employees}}...{{/employees}} 是循环开始和结束标记。{{index}} 是循环中自动生成的索引(从1开始)。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© 菜鸟-创作你的创作{{table}}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© 菜鸟-创作你的创作poi-tl 本身没有直接的合并API,但你可以在表格渲染完成后,使用 Apache POI 的API对目标表格单元格进行合并:
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© 菜鸟-创作你的创作功能 | 说明 |
|---|---|
动态表格渲染 | 使用循环占位符 或 MiniTableRenderData 实现 |
单元格合并 | 先渲染模板,再用Apache POI API对表格合并 |
推荐做法 | 模板设计时尽量预留合并单元格位置,代码灵活合并 |
明白!我帮你系统整理了一份 poi-tl全方位教程,包含:
模板示例:
| 序号 | 姓名 | 年龄 ||------|------|------|| {{#employees}} | {{index}} | {{name}} | {{age}} | {{/employees}} |php108 Bytes© 菜鸟-创作你的创作Java示例:
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© 菜鸟-创作你的创作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© 菜鸟-创作你的创作// 水平合并第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© 菜鸟-创作你的创作{{#xxx}}...{{/xxx}} 多层循环模板示例:
| 序号 | 姓名 | 项目列表 ||------|------|----------|| {{#employees}} | {{index}} | {{name}} | {{#projects}} - {{projectName}} ({{duration}}月) {{/projects}} {{/employees}} |php181 Bytes© 菜鸟-创作你的创作Java示例:
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© 菜鸟-创作你的创作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}} 占位符。
poi-tl支持条码,示例:
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© 菜鸟-创作你的创作https://www.52runoob.com/archives/5720
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。