首页 > 解决方案 > RepeatedHeaderTableDrawer 不显示多个页面中的所有行

问题描述

我正在尝试使用库 easytable 绘制一张大表(应该在多页中绘制)。
我使用类 RepeatedHeaderTableDrawer 在每个新页面中重复表头。标题将按预期显示。但问题是包含数据的表格的其余部分没有正确显示:显示的表格从应该显示的表格的开头没有变大(缺少一些行),最后一行也被重复并且结束所有数据行后,将显示更多重复行,直到最后一页结束。我知道这些问题合而为一,但可能是一种适应可以解决所有问题。

创建表的方法如下:

private static Table createCalculationTable() {

    final  Color ORANGE_DARK = new Color(245, 120, 60, 243);
    final  Color YELLOW_LIGHT = new Color(226, 212, 75, 255);
    final  Color ORANGE_LIGHT = new Color(234, 147, 90, 220);

    final Table.TableBuilder tableBuilder = Table.builder()
            .addColumnsOfWidth(100, 100, 100, 100, 100)            
            .fontSize(8)
            .font(HELVETICA)
            .borderColor(WHITE);

    // add the header row
    tableBuilder.addRow(Row.builder()
            .add(TextCell.builder().text("Name").horizontalAlignment(LEFT).borderWidth(1).build())
            .add(TextCell.builder().text("First Number").borderWidth(1).build())
            .add(TextCell.builder().text("Second Number").borderWidth(1).build())
            .add(TextCell.builder().text("Third Number").borderWidth(1).build())
            .add(TextCell.builder().text("TOTAL").borderWidth(1).build())
            .backgroundColor(ORANGE_DARK)
            .textColor(WHITE)
            .font(HELVETICA_BOLD)
            .fontSize(9)
            .horizontalAlignment(CENTER)
            .build());

    // add data rows
    double grandTotal = 0;
    for (int i = 0; i < DATA.length; i++) {
        final Object[] dataRow = DATA[i];
        final double total = (double) dataRow[2] / 60 * (double) dataRow[3];
        grandTotal += total;

        tableBuilder.addRow(Row.builder()
                .add(TextCell.builder().text(String.valueOf(dataRow[0])).horizontalAlignment(LEFT).borderWidth(1).build())
                .add(TextCell.builder().text(String.valueOf(dataRow[1])).borderWidth(1).build())
                .add(TextCell.builder().text(String.valueOf(dataRow[2])).borderWidth(1).build())
                .add(TextCell.builder().text(dataRow[3] + " €&quot;).borderWidth(1).build())
                .add(TextCell.builder().text(total + " €&quot;).borderWidth(1).build())
                .backgroundColor(i % 2 == 0 ? YELLOW_LIGHT : ORANGE_LIGHT)
                .horizontalAlignment(RIGHT)
                .build());
    }

    // add the final row
    tableBuilder.addRow(Row.builder()
            .add(TextCell.builder().text("Total")
                    .colSpan(4)
                    .lineSpacing(1f)
                    .borderWidthTop(1)
                    .textColor(WHITE)
                    .backgroundColor(ORANGE_DARK)
                    .fontSize(9)
                    .horizontalAlignment(CENTER)
                    .font(HELVETICA_OBLIQUE)
                    .borderWidth(1)
                    .build())
            .add(TextCell.builder().text(grandTotal + " €&quot;).backgroundColor(ORANGE_DARK)
                    .font(HELVETICA_BOLD_OBLIQUE)
                    .verticalAlignment(TOP)
                    .borderWidth(1)
                    .build())
            .horizontalAlignment(RIGHT)
            .build());

    return tableBuilder.build();
}

数据表定义如下:

 private final static Object[][] DATA = new Object[][]{
        {"BEGINNNN", 10.0, 150.0, 0.20},
        {"Location_1", 10.0, 150.0, 0.20},
        {"Location_11",   10.0, 200.0, 0.20},
        {"Location_111",    5.0, 200.0, 0.20},
        {"Location_1111",  5.0, 200.0, 0.20},
        {"Location_2",   10.0, 200.0, 0.20},
        {"Location_22",    5.0, 200.0, 0.20},
        {"Location_222",  5.0, 200.0, 0.20},
        {"Location_2222",   10.0, 200.0, 0.20},
        {"Location_3",    5.0, 200.0, 0.20},
        {"Location_33",  5.0, 200.0, 0.20},
        {"Location_333",   10.0, 200.0, 0.20},
        {"Location_3333",    5.0, 200.0, 0.20},
        {"Location_4",  5.0, 200.0, 0.20},
        {"Location_44",   10.0, 200.0, 0.20},
        {"Location_444",    5.0, 200.0, 0.20},
        {"Location_4444",  5.0, 200.0, 0.20},
        {"Location_5",   10.0, 200.0, 0.20},
        {"Location_55",    5.0, 200.0, 0.20},
        {"Location_555",  5.0, 200.0, 0.20},
        {"Location_5555",   10.0, 200.0, 0.20},
        {"Location_6",    5.0, 200.0, 0.20},
        {"Location_66",  5.0, 200.0, 0.20},
        {"Location_666",   10.0, 200.0, 0.20},
        {"Location_6666",    5.0, 200.0, 0.20},
        {"Location_66666",    5.0, 200.0, 0.20},
        {"Location_7",  5.0, 200.0, 0.20},
        {"Location_77",   10.0, 200.0, 0.20},
        {"Location_777",    5.0, 200.0, 0.20},
        {"Location_7777",  5.0, 200.0, 0.20},
        {"Location_77777",  5.0, 200.0, 0.20},
        {"Location_8",   10.0, 200.0, 0.20},
        {"Location_88",    5.0, 200.0, 0.20},
        {"Location_888",  5.0, 200.0, 0.20},
        {"Location_8888",   10.0, 200.0, 0.20},
        {"Location_88888",   10.0, 200.0, 0.20},
        {"Location_9",    5.0, 200.0, 0.20},
        {"Location_99",  5.0, 200.0, 0.20},
        {"Location_999",   10.0, 200.0, 0.20},
        {"Location_9999",    5.0, 200.0, 0.20},
        {"Location_99999",  5.0, 200.0, 0.20},
        {"Location_2",   10.0, 200.0, 0.20},
        {"Location_3",    5.0, 200.0, 0.20},
        {"Location_4",  5.0, 200.0, 0.20},
        {"Location_2",   10.0, 200.0, 0.20},
        {"Location_3",    5.0, 200.0, 0.20}, 
        {"Location_4",  5.0, 200.0, 0.20},   
        {"ENDDDDDD ",  5.0, 200.0, 0.20}
    };

以下方法调用 createCalculationTable 方法插入创建的表:

 public static void insertTable(String formPath, String formTargetPath) {

        try {
            PDDocument document = Loader.loadPDF(new File(formPath));
            final PDPage page = document.getPage(0);

            float startY = page.getMediaBox().getHeight() - PADDING;

            Table table = createCalculationTable();
            RepeatedHeaderTableDrawer.builder()           
                    .numberOfRowsToRepeat(1)
                    .page(page)
                    .table(table)                
                    .startX(PADDING )
                    .startY(startY )                             
                    .build()
                    .draw(() -> document, () -> page, PADDING);            
            document.save(formTargetPath);
            document.close();
        }
        catch (Exception e) {
            throw new ObjectNotFoundException("PDF file couldn't be created");
        }
    }

我检查了数据何时恰好适合一页,整个表格将正确显示。但是当只有一行不适合第一页时,我会遇到下面提到的不同问题。我几乎可以肯定,RepeatedHeaderTableDrawer.builder() 的 .endY(value) 可以解决数据结束后重复行的问题。这意味着当没有更多数据时,表格将结束,并且直到最后一页结束时才会显示冗余行,例如当前的情况。但我不知道如何将此值设置为“当没有更多原始数据时”,因为该表是可变的并且它没有固定大小。任何想法/帮助将不胜感激。谢谢

标签: javapdfbox

解决方案


draw() 方法的第二个参数接受一个供应商,而不仅仅是一个页面。不同之处在于,库不是分配新页面,而是尝试一遍又一遍地使用同一页面。

这应该有效:

RepeatedHeaderTableDrawer.builder()           
                .numberOfRowsToRepeat(1)
                .page(page)
                .table(table)                
                .startX(PADDING )
                .startY(startY )                             
                .build()
                .draw(() -> document, () -> new PDPage(), PADDING);

推荐阅读