phax / ph-pdf-layout

Java library for creating fluid page layouts with Apache PDFBox. Supporting multi-page tables, different page layouts etc.
Apache License 2.0
64 stars 11 forks source link

An error occurs when using setVertSplittable(false) if the string in the table is very long. #43

Open walter-chequer opened 1 month ago

walter-chequer commented 1 month ago

I used setVertSplittable(false) on PLText to prevent page breaks. However, when there is an exceptionally long string in a cell that must overflow to the next page, the following error occurs. Is there a solution for this?

Internal error
com.helger.pdflayout.PDFCreationException: Internal error
    at com.helger.pdflayout.PageLayoutPDF.renderTo(PageLayoutPDF.java:420)
    at com.helger.pdflayout.PageLayoutPDF.renderTo(PageLayoutPDF.java:586)
    at PhPdfLayoutTest.pdfTableTest3(PhPdfLayoutTest.kt:516)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: java.lang.IllegalArgumentException: The value of 'StartTop' must be >= 0! The current value is: -430.2044
    at com.helger.commons.ValueEnforcer.isGE0(ValueEnforcer.java:1742)
    at com.helger.commons.ValueEnforcer.isGE0(ValueEnforcer.java:1733)
    at com.helger.pdflayout.render.PageRenderContext.<init>(PageRenderContext.java:92)
    at com.helger.pdflayout.render.PageRenderContext.<init>(PageRenderContext.java:63)
    at com.helger.pdflayout.element.vbox.AbstractPLVBox.onRender(AbstractPLVBox.java:898)
    at com.helger.pdflayout.base.AbstractPLRenderableObject.render(AbstractPLRenderableObject.java:311)
    at com.helger.pdflayout.element.table.PLTable.onRender(PLTable.java:501)
    at com.helger.pdflayout.base.AbstractPLRenderableObject.render(AbstractPLRenderableObject.java:311)
    at com.helger.pdflayout.base.PLPageSet.renderAllPages(PLPageSet.java:1071)
    at com.helger.pdflayout.PageLayoutPDF.renderTo(PageLayoutPDF.java:392)
    ... 5 more

The value of 'StartTop' must be >= 0! The current value is: -430.2044
java.lang.IllegalArgumentException: The value of 'StartTop' must be >= 0! The current value is: -430.2044
    at com.helger.commons.ValueEnforcer.isGE0(ValueEnforcer.java:1742)
    at com.helger.commons.ValueEnforcer.isGE0(ValueEnforcer.java:1733)
    at com.helger.pdflayout.render.PageRenderContext.<init>(PageRenderContext.java:92)
    at com.helger.pdflayout.render.PageRenderContext.<init>(PageRenderContext.java:63)
    at com.helger.pdflayout.element.vbox.AbstractPLVBox.onRender(AbstractPLVBox.java:898)
    at com.helger.pdflayout.base.AbstractPLRenderableObject.render(AbstractPLRenderableObject.java:311)
    at com.helger.pdflayout.element.table.PLTable.onRender(PLTable.java:501)
    at com.helger.pdflayout.base.AbstractPLRenderableObject.render(AbstractPLRenderableObject.java:311)
    at com.helger.pdflayout.base.PLPageSet.renderAllPages(PLPageSet.java:1071)
    at com.helger.pdflayout.PageLayoutPDF.renderTo(PageLayoutPDF.java:392)
    at com.helger.pdflayout.PageLayoutPDF.renderTo(PageLayoutPDF.java:586)
    at PhPdfLayoutTest.pdfTableTest3(PhPdfLayoutTest.kt:516)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

Here is the code I used.

        val landscapeA4 = PDRectangle(PDRectangle.A4.height, PDRectangle.A4.width)
        val pageSet = PLPageSet(landscapeA4).setMargin(40f)

        val r10 = FontSpec(PreloadFont.REGULAR, 10f)
        val r14b = FontSpec(PreloadFont.REGULAR, 10f)
        val aPadding = PaddingSpec(2f)

        val aTable = PLTable.createWithEvenlySizedColumns(4)
        aTable.setHeaderRowCount(1)
        aTable.setMargin(10f)

        // Add header row
        val aHeaderRow = aTable.addAndReturnRow(
            PLTableCell(PLText("No", r14b).setPadding(aPadding)),
            PLTableCell(PLText("B", r14b).setPadding(aPadding)),
            PLTableCell(PLText("C", r14b).setPadding(aPadding)),
            PLTableCell(PLText("Page Break", r14b).setPadding(aPadding)),
        )
        aHeaderRow.setFillColor(PLColor.GRAY)

        val longString = "1234567890\n" + "pagebreak".repeat(150)
        val row = listOf("column B", "column C", longString)
        for (i in 0..10) {
            aTable.addRow(
                PLTableCell(PLText(i.toString(), r10).setPadding(aPadding).setVertSplittable(false)),
                PLTableCell(PLText(row[0], r10).setPadding(aPadding).setVertSplittable(false)),
                PLTableCell(PLText(row[1], r10).setPadding(aPadding).setVertSplittable(false)),
                PLTableCell(PLText(row[2], r10).setPadding(aPadding).setVertSplittable(false)),
            )
        }

        EPLTableGridType.FULL.applyGridToTable(aTable, BorderStyleSpec(PLColor.BLACK, 1f))
        pageSet.addElement(aTable)

        val pageLayout = PageLayoutPDF()
        pageLayout.addPageSet(pageSet)

        pageLayout.renderTo(File("page-break-sample.pdf"))

Thank you for your always kind responses. :)

phax commented 3 weeks ago

@walter-chequer sorry for the delay. Indeed, there is currently no solution for this. So it is either splittable or not - no differentiation so far. However, what I can think of is some additional flag like "only split vertically if it exceeds the page height" or so - exactly to avoid the scenario you are mentioning. Basically it means "No split, but instead of an error split". Does that sound reaosnable to you?

walter-chequer commented 2 weeks ago

@phax Sure, that would be great.