iTextSharp: SplitLate/SplitRows?

Jason picture Jason · Sep 1, 2009 · Viewed 23k times · Source

I have an issue where I have a table (PdfPTable) that may extend past the length of the page. I have tried looking up how to "split" a table onto more than one page but iTextSharp is pretty poorly documented in this area. Does anyone know how to do this without choosing an arbitrary Y position on the page and telling it to split if it's there?

I looked into the SplitLate and SplitRows properties, but there's no documentation on what these do. EDIT They do nothing.

Thanks!

EDIT

I'm looking to cut the table in half widthwise as the table will always fit the width of the page. This is to say that I want the rows that don't fit vertically to extend to the next page below it.

EDIT2

Here's some code:

Public Sub BuildPrintableDocument
    Dim doc As New Document(PageSize.LETTER, 0, 0, 0, BOTTOM_MARGIN)
    Dim writer As PdfWriter = PdfWriter.GetInstance(doc, _
        New FileStream("invoice.pdf", FileMode.Create)

    Dim footer As New HeaderFooter(New Phrase("www.columbussupply.com", _
        footerFont), False)
    footer.Border = Rectangle.NO_BORDER
    footer.Alignment = HeaderFooter.ALIGN_CENTER
    doc.Footer = footer

    doc.Open()

....

Dim items As PdfPTable = NewItemTable()
Dim count As Integer = 0
    For Each oi As OrderItem In TheInvoice.Items
        If oi.Status <> OrderItem.OrderItemStatus.Cancelled Then
            Dim qty As New PdfPCell(New Phrase(oi.Quantity, mainFont))
            qty.HorizontalAlignment = Element.ALIGN_CENTER
            qty.Padding = ITEMS_PADDING

            '...instantiate 3 other cells here (removed for repetitiveness)'

            items.AddCell(qty)
            items.AddCell(desc)
            items.AddCell(price)
            items.AddCell(total)
        End If
    Next

    items.WriteSelectedRows(0, -1, LEFT_MARGIN, GetItemsStartY, _
        writer.DirectContent)
End Sub


Protected Function NewItemTable() As PdfPTable
    Dim items As PdfPTable = New PdfPTable(4)
    Dim headers() As String = {"QTY", "DESCRIPTION", "PRICE", "TOTAL"}

    For Each s As String In headers
        Dim cell As New PdfPCell(New Phrase(s, mainFont))
        cell.HorizontalAlignment = Element.ALIGN_CENTER
        items.AddCell(cell)
    Next

    items.TotalWidth = ITEMS_TOTAL_WIDTH
    items.SetWidths(New Single() {QTY_COL_WIDTH, DESC_COL_WIDTH, _ 
        PRICE_COL_WIDTH, TOTALS_COL_WIDTH})
    Return items
End Function

Answer

asgerhallas picture asgerhallas · Nov 7, 2009

You should add the table to the document using Document.Add() if you want automatic splitting of the rows across pages. Then SplitLate and SplitRows will work as expected.

  1. When SplitLate = true (default) the table will be split before the next row that does fit on the page.
  2. When SplitLate = false the row that does not fully fit on the page will be split.
  3. When SplitRows = true (default) the row that does not fit on a page will be split.
  4. When SplitRows = false the row will be omitted.

So

  • SplitLate && SplitRows: A row that does not fit on the page will be started on the next page and eventually split if it does not fit on that page either.

  • SplitLate && !SplitRows: A row that does not fit on the page will be started on the next page and omitted if it does not fit on that page either.

  • !SplitLate && SplitRows: A row that does not fit on the page will be split and continued on the next page and split again if it too large for the next page too.

  • !SplitLate && !SplitRows: I'm a little unsure about this one. But from the sources it looks like it's the same as SplitLate && !SplitRows: A row that does not fit on the page will be started on the next page and omitted if it does not fit on that page either.

But as for your question: Document.Add() will only be usable if the table is not needed to be absolutely positioned. But it's seems like there is a way to do it though by adding the table to a ColumnText (it's actually a ColumnText object that does all the table splitting) and then absolutely positioning that ColumnText. I haven't looked into it yet, but I will as soon as I get a little more time :)