Java easytable – Create rows in table using for loop

I am trying to use vandeseer’s easytable to create a table with a header row and then a number of rows created using a for loop.

The best i’ve been able to do is create two seperate table and align them under each other. The first table being the header row and the second table where I want the for loop to populate a number of rows. This is what it looks like when rendered using PDFBox.

See what I have here

My current code:

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();
            
}

I’ve tried to use a for loop to populate the rows, as below, but it obviously doesn’t work.

            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();

                }

I’ve tried looking in the documentation but can’t seem to find anything similar. I’ve seen examples using Table.TableBuilder but for some reason these table won’t render on the pdf. Hence why I’ve used just the Table class.

Answer

That should be straightforward. Have you had a look at this Q/A? I guess you want to repeat the header row on every new page, right? If so, it should be as simple as:

RepeatedHeaderTableDrawer.builder()
    .table(createTable())
    .startX(50)
    .startY(100F)
    .endY(50F) // <-- If the table is bigger, a new page is started
    .build()

Maybe also have a look at this class.

UPDATE:

If it’s really only about using a for loop for populating the rows below the header, the trick is to assign the TableBuilder to a local variable. The following illustrates that with a minimal working solution:

try (final PDDocument document = new PDDocument()) {
    final PDPage page = new PDPage(PDRectangle.A4);
    document.addPage(page);

    try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {

        // Build the table
        final Table.TableBuilder myTableBuilder = Table.builder()
                .addColumnsOfWidth(200, 200)
                .padding(2)
                .addRow(Row.builder()
                        .add(TextCell.builder().text("Header 1").build())
                        .add(TextCell.builder().text("Header 2").build())
                        .build());

        for (int i = 0; i < 20; i++) {
            myTableBuilder
                    .addRow(Row.builder()
                            .add(TextCell.builder().text("1st cell on row " + i).build())
                            .add(TextCell.builder().text("2nd cell on row " + i).build())
                            .build())
                    .build();
        }

        // Set up the drawer
        TableDrawer tableDrawer = TableDrawer.builder()
                .contentStream(contentStream)
                .startX(20f)
                .startY(page.getMediaBox().getUpperRightY() - 20f)
                .table(myTableBuilder.build())
                .build();

        // And go for it!
        tableDrawer.draw();
    }

    document.save("example.pdf");
}