Can I use an iTextSharp cell event to repeat data

2019-08-24 02:20发布

问题:

I have a very deep row in a pdfptable. The columns in the left-hand side of this row contain a sub table which has many rows within it. I would like the deep row to split onto more than one page if it is too deep to fit on one page. I can set SplitLate to false to ensure that the row splits. However, the data for the deep columns on the right hand side only shows on the first page and I would like it to be repeated on the second page.

A bit of investigation suggested that I could use a cell event to put the text into the cells and have it repeated on the second page. So I created a cell event as follows:

Public Class PdfPCellEvent
Implements iTextSharp.text.pdf.IPdfPCellEvent

Private m_text As String
Private m_font As text.pdf.BaseFont

Public Sub New(ByVal text As String, font As text.pdf.BaseFont)
    MyBase.New()

    m_text = text
    m_font = font

End Sub

Public Sub CellLayout(cell As PdfPCell, position As text.Rectangle, canvases() As PdfContentByte) Implements IPdfPCellEvent.CellLayout

    Dim cb As PdfContentByte = canvases(PdfPTable.TEXTCANVAS)
    cb.BeginText()
    cb.SetFontAndSize(m_font, 8)
    cb.ShowText(m_text)
    cb.EndText()

End Sub

End Class

I then call this as follows:

Dim cell As PdfPCell = New PdfPCell()
Dim bfReport As BaseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, False)

Dim cellEvent As New PdfPCellEvent("Text", bfReport)
cell.CellEvent = cellEvent
mainTable.AddCell(cell)

document.Add(mainTable)

This all runs. I can see that the cell event is being called twice after the mainTable is added to the document. I presume it is being called once for each page the row appears on. I can also see that the correct text is being passed into CellLayout. However no text appears in the resulting pdf. What am I doing wrong? I have tried various ways of adding the text in CellLayout but none have worked.

回答1:

There is something missing in this code snippet:

Dim cb As PdfContentByte = canvases(PdfPTable.TEXTCANVAS)
cb.BeginText()
cb.SetFontAndSize(m_font, 8)
cb.ShowText(m_text)
cb.EndText()

You are creating a text block, but you forget to specify coordinates. I suspect that the BT/ET sequence is added to the content stream, but there's no way of telling where the text will show up on the page.

In the cell layout, you have access to position As text.Rectangle. You can ask the position variable for coordinates. You can use these coordinates in the code snippet about (using the SetTextMatrix() method), but it will be easier for you if you don't use cb.BeginText(), cb.SetFontAndSize(), cb.SetTextMatrix(), cb.ShowText(), cb.EndText(). Use ColumnText.ShowTextAligned() instead. You can pass the cb instance as a parameter, along with a Phrase, an alignment (left, right, center), an X,Y coordinate and an angle.



回答2:

Thanks, the following now works perfectly:

Public Class PdfPCellEvent
Implements iTextSharp.text.pdf.IPdfPCellEvent

Private m_phrase As text.Phrase

Public Sub New(ByVal phrase As text.Phrase)
    MyBase.New()

    m_phrase = phrase

End Sub

Public Sub CellLayout(cell As PdfPCell, position As text.Rectangle, canvases() As PdfContentByte) Implements IPdfPCellEvent.CellLayout

    Dim cb As PdfContentByte = canvases(PdfPTable.TEXTCANVAS)
    Dim CenterX As Single = position.GetLeft(0) + (position.Width() / 2)
    Dim CenterY As Single = position.GetBottom(0) + (position.Height() / 2)
    ColumnText.ShowTextAligned(cb, text.Element.ALIGN_CENTER, m_phrase, CenterX, CenterY, 0)

End Sub

End Class

And I call this as follows:

phrase = New text.Phrase("Text", fontSmaller)
Dim cell As PdfPCell = New PdfPCell()
Dim cellEvent As New PdfPCellEvent(phrase)
cell.CellEvent = cellEvent
mainTable.AddCell(cell)
document.Add(mainTable)

The text now appears on both pages and is centred vertically and horizontally in the cell.