You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java使用easytable通过for循环批量生成表格数据行的实现问题

问题背景

我正在尝试使用vandeseer的easytable库创建包含表头行、且剩余数据行通过for循环生成的表格。目前我仅能实现创建两个独立表格上下对齐摆放,第一个表格存放表头行,第二个表格用来承载for循环生成的多行内容,使用PDFBox渲染后的效果如下:
渲染效果

我当前的实现代码如下:

private void drawActiveCelUserRolesTable(PDPageContentStream contentStream, List<CelUser> users) {

            //draw table header
            Table activeUsersHeader = Table.builder()
                    .addColumnsOfWidth(100,100,100,100,100)
                    .addRow(Row.builder()
                            .add(TextCell.builder().text("Last Name").borderWidth(1).build())
                            .add(TextCell.builder().text("First Name").borderWidth(1).build())
                            .add(TextCell.builder().text("Role Name").borderWidth(1).build())
                            .add(TextCell.builder().text("Effective Date").borderWidth(1).build())
                            .add(TextCell.builder().text("Expiry Date").borderWidth(1).build())
                            .build())

                    .build();

            TableDrawer headerDrawer = TableDrawer.builder()
                    .contentStream(contentStream)
                    .startX(HEADER_TABLE_LOCATION_X)
                    .startY(HEADER_TABLE_LOCATION_Y-50)
                    .table(activeUsersHeader)
                    .build();

            headerDrawer.draw();

            Table activeUsersRows = Table.builder()
                    .addColumnsOfWidth(100,100,100,100,100)
                    .addRow(Row.builder()
                            .add(TextCell.builder().text("Joe").borderWidth(1).build())
                            .add(TextCell.builder().text("Bob").borderWidth(1).build())
                            .add(TextCell.builder().text("ADM").borderWidth(1).build())
                            .add(TextCell.builder().text("17/12/20").borderWidth(1).build())
                            .add(TextCell.builder().text("17/12/21").borderWidth(1).build())
                            .build())

                    .build();

            TableDrawer rowDrawer = TableDrawer.builder()
                    .contentStream(contentStream)
                    .startX(HEADER_TABLE_LOCATION_X)
                    .startY(HEADER_TABLE_LOCATION_Y - 67)
                    .table(activeUsersRows)
                    .build();

            rowDrawer.draw();
            
}

我尝试通过如下写法用for循环填充表格行,但是代码显然无法正常运行:

Table activeUsersRows = Table.builder()
                .addColumnsOfWidth(100,100,100,100,100)
                for (int i = 0; i < 5; i++) {

                    .addRow(Row.builder()
                            .add(TextCell.builder().text("Joe").borderWidth(1).build())
                            .add(TextCell.builder().text("Bob").borderWidth(1).build())
                            .add(TextCell.builder().text("ADM").borderWidth(1).build())
                            .add(TextCell.builder().text("17/12/20").borderWidth(1).build())
                            .add(TextCell.builder().text("17/12/21").borderWidth(1).build())
                            .build())

                    .build();

                }

我查阅了官方文档,没有找到类似的实现案例。我也见过使用Table.TableBuilder的示例,但不知为何这类写法生成的表格无法在PDF中渲染,因此我目前仅使用Table类实现。请问我要如何正确通过for循环在同一个easytable表格中批量生成数据行?


解决方案

你原来的写法错误是因为Java的链式调用不能中间插入for循环语句,正确的做法是先单独实例化TableBuilder对象,循环调用addRow方法,最后再调用build生成Table对象即可,不需要拆成两个独立表格。

完整的修正后代码如下:

private void drawActiveCelUserRolesTable(PDPageContentStream contentStream, List<CelUser> users) throws IOException {
    // 先创建TableBuilder对象,不要直接链式build
    Table.TableBuilder tableBuilder = Table.builder()
            .addColumnsOfWidth(100,100,100,100,100);
    
    // 先添加表头行
    tableBuilder.addRow(Row.builder()
            .add(TextCell.builder().text("Last Name").borderWidth(1).build())
            .add(TextCell.builder().text("First Name").borderWidth(1).build())
            .add(TextCell.builder().text("Role Name").borderWidth(1).build())
            .add(TextCell.builder().text("Effective Date").borderWidth(1).build())
            .add(TextCell.builder().text("Expiry Date").borderWidth(1).build())
            .build());
    
    // 循环添加数据行,这里可以遍历你传入的users集合替换示例内容
    for (CelUser user : users) {
        tableBuilder.addRow(Row.builder()
                .add(TextCell.builder().text(user.getLastName()).borderWidth(1).build())
                .add(TextCell.builder().text(user.getFirstName()).borderWidth(1).build())
                .add(TextCell.builder().text(user.getRoleName()).borderWidth(1).build())
                // 日期格式化可以根据你的需求自行调整
                .add(TextCell.builder().text(user.getEffectiveDate().format(DateTimeFormatter.ofPattern("dd/MM/yy"))).borderWidth(1).build())
                .add(TextCell.builder().text(user.getExpiryDate().format(DateTimeFormatter.ofPattern("dd/MM/yy"))).borderWidth(1).build())
                .build());
    }
    
    // 所有行添加完成后再build生成完整表格
    Table fullTable = tableBuilder.build();
    
    // 一次性渲染整个表格,不需要拆分表头和内容分别渲染
    TableDrawer tableDrawer = TableDrawer.builder()
            .contentStream(contentStream)
            .startX(HEADER_TABLE_LOCATION_X)
            .startY(HEADER_TABLE_LOCATION_Y - 50)
            .table(fullTable)
            .build();
    
    tableDrawer.draw();
}

如果之前用TableBuilder渲染失败,大概率是你没有在所有行添加完成后才调用build方法,或者是渲染的起始Y坐标设置不对(PDF的坐标系原点在左下角,Y值越小位置越靠下,如果设置的Y值过小会导致表格渲染到页面可视区域外)。


内容的提问来源于stack exchange,提问作者KikiZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 00:42:04