word导出 poi-tl 动态表格、合并单元格


1、动态表格 {{#var}}
2、列表 {{*var}}
3、区块对 {{?sections}} {{/sections}}
4、SpringEL表达式使用
5、表格单元格合并
注意:表格外使用{{test}},表格内使用[test] 设置变量

一、动态表格

1、使用TableRenderData

eg1: 基础表格

// 一个2行2列的表格
put("table0", Tables.of(new String[][] {
                new String[] { "00", "01" },
                new String[] { "10", "11" }
            }).border(BorderStyle.DEFAULT).create());

在这里插入图片描述

eg2:表格样式示例

// 表头居中且背景为蓝色
RowRenderData row0 = Rows.of("姓名", "学历").textColor("FFFFFF")
      .bgColor("4472C4").center().create();
RowRenderData row1 = Rows.create("李四", "博士");
put("table1", Tables.create(row0, row1));

在这里插入图片描述

2、使用List方式

![word中表格,表头固定](https://img-blog.csdnimg.cn/c6242c1a70e24faf9db63101a1430dc1.png)
上图为word中表格,表头固定
List<Map<String, Object>> table1 = new ArrayList<>();
for(int i = 0; i < 5; i++) {
		Map<String, Object> zkMap = new HashMap<>();
        zkMap.put("name", "张三" + i);
        zkMap.put("age", 25);
        zkMap.put("job", "xxx");
        zkMap.put("conten", "xxx");
        zkMap.put("year", "2023");
        table1.add(zkMap);
}

二、列表

1、NumberingRenderData

eg1:默认

map.put("list", Numberings.create("Plug-in grammar",
                    "Supports word text, pictures, table...",
                    "Not just templates"));

eg2:设置编号样式Numberings.of(NumberingFormat)

// DECIMAL //1. 2. 3.
// DECIMAL_PARENTHESES //1) 2) 3)
// BULLET //● ● ●
// LOWER_LETTER //a. b. c.
// LOWER_ROMAN //i ⅱ ⅲ
// UPPER_LETTER //A. B. C.
map.put("list", Numberings.of(NumberingFormat.DECIMAL)
	.addItem("Plug-in grammar")
	.addItem("Supports word text").create());

2、List

三、区块对 {{?sections}}{{/sections}}

标签内的内容:false或空集合时不显示标签元素
循环中的内置变量:
在这里插入图片描述

eg1:简单示例
{{?ex}}
{{titile}}
{{/ex}}


eg2:表格循环

word 示例:
在这里插入图片描述
最外层的类:

@Data
public class TReportInformDataVO {

    @ApiModelProperty(value = "报告日期")
    private String generateDate;
    
    @ApiModelProperty(value = "gk数据")
    private List<InformGKDataVO> GKDESC;
    
}

循环表格的类:

@Data
    public static class InformGKDataVO {

        @ApiModelProperty(value = "表格index")
        private Integer index;

        @ApiModelProperty(value = "企业名称")
        private String entName;

        private String reportYear;

        private String reportMonth;

        @ApiModelProperty(value = "gk数据表格")
        private List<InformGKTableDataVO> gkTable;

        @Data
        public static class InformGKTableDataVO {

            @ApiModelProperty(value = "名称")
            private String name;

            @ApiModelProperty(value = "数据项")
            private String item;

            @ApiModelProperty(value = "单位")
            private String unit;

            @ApiModelProperty(value = "填报值")
            private String reportData;

            @ApiModelProperty(value = "gk数据")
            private String gkData;

            @ApiModelProperty(value = "偏差")
            private String offset;

        }
    }

结果如下:

在这里插入图片描述

四、SpringEL表达式使用

注意:
1、使用SpringEL表达式需要将标签配置为SpringEL模式
2、表达式在idea 或 其他文本工具 写好后再复制到word文档中

// java
builder.useSpringEL();

SpringEL表达式:

# 日期格式化
{{new java.text.SimpleDateFormat('yyyy-MM-dd HH:mm:ss').format(time)}} 
# 三目运算
{{sex ? '男' : '女'}} 
# 设置文本样式:可以使用el表达式,也可以在java代码里设置
[status=='0'?'通过':new com.deepoove.poi.data.TextRenderData('FF0000','不通过')]

五、表格单元格合并

合并单元格的Policy,继承DynamicTableRenderPolicy

@Accessors(chain = true)
public class MergeRowModelRenderPolicy extends DynamicTableRenderPolicy {
    // 需要合并的列,从0开始
    List<Integer> mergeColumns = Arrays.asList(0);
    // 表格所有的列数
    Integer colNum = 5;

    @Override
    public void render(XWPFTable table, Object data) throws Exception {
        if (data == null) {
            return;
        }
        if (CollUtil.isEmpty(mergeColumns)) {
            return;
        }
        if (colNum == null) {
            return;
        }
        
        // 需要处理的数据
        List<TReportInformDataVO.InformGKDataVO.InformGKTableDataVO> dataList = (List<TReportInformDataVO.InformGKDataVO.InformGKTableDataVO>) data;

		// 表格所有行
        List<RowRenderData> detailData = new ArrayList<>();
        if (data != null) {
            table.removeRow(1);
            for (int i = dataList.size() - 1; i >= 0; i--) {
                //根据数据长度创建对应行数
                XWPFTableRow insertNewTableRow = table.insertNewTableRow(1);
                for (int j = 0; j < colNum; j++) {
                    //根据列的数量创建对应单元格
                    insertNewTableRow.createCell();
                }
                // 单行渲染
                TReportInformDataVO.InformGKDataVO.InformGKTableDataVO item = dataList.get(i);
                // rowBuilder.center().verticalCenter() 表格内容居中
                // rowBuilder.rowAtleastHeight(1) 设置表格高度
                RowRenderData rowRenderData = Rows.of(item.getGeneratorSystemName(), item.getItem() + "(" + item.getUnit() + ")", item.getReportData(), item.getGkData(), item.getOffset()).center().verticalCenter().rowAtleastHeight(1).create();
                detailData.add(rowRenderData);
                // 填充表格
                TableRenderPolicy.Helper.renderRow(table.getRow(1), rowRenderData);
            }

            List<Map<Integer, MergeRowVo>> lstCol = new ArrayList<>();
            // 循环列
            mergeColumns.forEach(x -> {
                Map<Integer, MergeRowVo> mapsCol = new HashMap<>();
                for (int i = 0; i < detailData.size(); i++) {
                	// 要和下一行的内容比较,避免数组越界
                    if (i + 1 > detailData.size() - 1) {
                        break;
                    }
                  
                    List<CellRenderData> cells = detailData.get(i).getCells();
                    List<CellRenderData> nextCells = detailData.get(i + 1).getCells();
					// ***默认单元格合并要参考第0列
                    if (cells.get(0).getParagraphs().get(0).getContents().get(0).toString().equals(nextCells.get(0).getParagraphs().get(0).getContents().get(0).toString())) {
                    // 判断第x列 == 第x+1列 ?
                        if (cells.get(x).getParagraphs().get(0).getContents().get(0).toString().equals(nextCells.get(x).getParagraphs().get(0).getContents().get(0).toString())) {
                            if (mapsCol.containsKey(x)) {
                                mapsCol.put(x, new MergeRowVo().setStartRow(mapsCol.get(x).getStartRow()).setEndRow(i + 2));
                            } else {
                                mapsCol.put(x, new MergeRowVo().setStartRow(i + 1).setEndRow(i + 2));
                            }
                        }
                    } else {
                        lstCol.add(new HashMap<>(mapsCol));
                        mapsCol.clear();
                    }
                }
                if (mapsCol.size() > 0) {
                    lstCol.add(new HashMap<>(mapsCol));
                    mapsCol.clear();
                }
            });
            lstCol.forEach(mapsCol -> {
                mapsCol.keySet().forEach(key -> {
                // 单元格合并
                    TableTools.mergeCellsVertically(table, key, mapsCol.get(key).getStartRow(), mapsCol.get(key).getEndRow());
                });
            });
        }
    }
}

六、官方示例

地址:
poi-tl官方示例:http://deepoove.com/poi-tl/#_%E7%A4%BA%E4%BE%8B_5

好的,如果您要使用poi-tl导出Word文档并合并单元格,可以按照以下步骤进行操作: 1. 首先,准备一个Word模板文件,其中包含需要合并单元格表格。可以使用MS Word或其他工具创建模板文件。在模板文件中,使用`${}`占位符来标识需要填充数据的位置,使用`#for`和`#end`标记来循环生成多行数据。示例模板文件如下: ``` 姓名\t性别\t年龄\t住址 #for(user in users) ${user.name}\t${user.gender}\t${user.age}\t${user.address} #end ``` 2. 在Java代码中,使用poi-tl的模板引擎来加载模板文件,并将数据绑定到模板中。在模板中,使用`#merge`标记来指定需要合并的单元格区域。示例代码如下: ```java // 加载模板文件 InputStream is = new FileInputStream("template.docx"); XWPFTemplate template = XWPFTemplate.compile(is).render(new HashMap<String, Object>() {{ // 绑定数据 List<User> users = Arrays.asList( new User("张三", "男", 20, "北京"), new User("李四", "女", 22, "上海"), new User("王五", "男", 25, "广州") ); put("users", users); }}); // 获取表格合并单元格 IBody body = template.getDocument().getBody(); List<XWPFTable> tables = body.getTables(); XWPFTable table = tables.get(0); // 假设第一个表格需要合并单元格 table.getRow(0).getCell(0).setText("姓名"); table.getRow(0).getCell(1).setText("性别"); table.getRow(0).getCell(2).setText("年龄"); table.getRow(0).getCell(3).setText("住址"); for (int i = 1; i <= 3; i++) { table.getRow(i).getCell(0).setText("#{" + "users[" + (i - 1) + "].name}"); table.getRow(i).getCell(1).setText("#{" + "users[" + (i - 1) + "].gender}"); table.getRow(i).getCell(2).setText("#{" + "users[" + (i - 1) + "].age}"); table.getRow(i).getCell(3).setText("#{" + "users[" + (i - 1) + "].address}"); } table.mergeCells(1, 1, 2, 2); // 合并单元格 // 导出文档 template.write(new FileOutputStream("output.docx")); template.close(); ``` 在模板中,使用`${}`占位符来引用数据对象的字段,使用`#merge`标记来指定需要合并的单元格区域。在Java代码中,使用`table.mergeCells()`方法来合并单元格,其中参数分别为起始行、起始列、结束行、结束列。在本例中,我们将第2行第2列到第3行第3列的单元格进行了合并。 希望这些信息能够对您有所帮助!如果您还有其他问题,请随时提出。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值