如何在使用iTextSharp生成的动态生成的PDF中的某些页面上执行不同的操作?

时间:2011-03-21 09:46:09

标签: c# pdf-generation itextsharp

我正在使用iTextSharp动态生成PDF文档。我不知道它将包含多少页面。我已经设法通过覆盖PdfPageEventHelper上的OnStartPage和OnEndPage来在所有页面上创建页眉和页脚。 但是,使用这种方法,所有页面上的标题都相同,并且所有页面上的页脚都相同。我需要更有活力:我需要在最后一页显示不同的页脚。

当我在OnEndPage方法中时,我知道页面的页面编号,但我不知道它是否是最后一个。当我在OnCloseDocument方法中时,我知道总页数,但我不能从这里“删除”或“删除”或更改OnEndPage添加到最后一页的页脚。

2 个答案:

答案 0 :(得分:0)

所以你有一个创建页面和添加内容的主循环代码,对吧?完成该内容后,您可以设置OnEndPage查找的全局标记吗?

下面的代码(在VB.Net中,抱歉)用一个布尔变量创建一个类(所以我们可以通过引用传递它),一旦我们完成主处理循环,我们设置为true,这样OnEndPage知道要做些不同的事情。对于详细IPdfPageEvent抱歉,VB要求所有方法都被声明,即使你不使用它们。

Option Explicit On
Option Strict On

Imports iTextSharp.text
Imports iTextSharp.text.pdf
Imports System.IO

Public Class Form1
    ''//Holds our state information
    Private PageState As CustomPageState
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ''//Create a new document
        Dim Doc As New iTextSharp.text.Document(PageSize.LETTER)

        ''//Write it to a memory stream
        Using FS As New FileStream(Path.Combine(My.Computer.FileSystem.SpecialDirectories.Desktop, "Output.pdf"), FileMode.Create, FileAccess.Write, FileShare.Read)
            ''//Grab the writer
            Dim writer = PdfWriter.GetInstance(Doc, FS)
            ''//Create an object that we can pass by reference around to store the page state
            Me.PageState = New CustomPageState()
            ''//Wire our event handler and pass in the page state
            writer.PageEvent = New MyCustomPdfEvent(Me.PageState)
            ''//Open the PDF for writing
            Doc.Open()

            ''//Main loop, create a bunch of pages
            For I = 1 To 10
                Doc.NewPage()
                Doc.Add(New Phrase("Hello"))

                ''//This code goes at the very end of our main loop
                If I = 10 Then Me.PageState.IsLastPage = True
            Next
            ''//Close the PDF
            Doc.Close()

        End Using
    End Sub
    ''//This is our state container. Its just has a boolean value but its wrapped in a class so that we can pass it around by reference
    Public Class CustomPageState
        Public Property IsLastPage As Boolean = False
    End Class

    Public Class MyCustomPdfEvent
        Implements IPdfPageEvent
        ''//Reference to the state container
        Private PageState As CustomPageState

        Public Sub New(ByRef pageState As CustomPageState)
            Me.PageState = pageState
        End Sub

        Public Sub OnEndPage(ByVal writer As iTextSharp.text.pdf.PdfWriter, ByVal document As iTextSharp.text.Document) Implements iTextSharp.text.pdf.IPdfPageEvent.OnEndPage
            If Me.PageState.IsLastPage Then
                ''//Last page, do something different
            Else
                ''//Do normal page footer
            End If
        End Sub

        Public Sub OnChapter(ByVal writer As iTextSharp.text.pdf.PdfWriter, ByVal document As iTextSharp.text.Document, ByVal paragraphPosition As Single, ByVal title As iTextSharp.text.Paragraph) Implements iTextSharp.text.pdf.IPdfPageEvent.OnChapter

        End Sub

        Public Sub OnChapterEnd(ByVal writer As iTextSharp.text.pdf.PdfWriter, ByVal document As iTextSharp.text.Document, ByVal paragraphPosition As Single) Implements iTextSharp.text.pdf.IPdfPageEvent.OnChapterEnd

        End Sub

        Public Sub OnCloseDocument(ByVal writer As iTextSharp.text.pdf.PdfWriter, ByVal document As iTextSharp.text.Document) Implements iTextSharp.text.pdf.IPdfPageEvent.OnCloseDocument

        End Sub

        Public Sub OnGenericTag(ByVal writer As iTextSharp.text.pdf.PdfWriter, ByVal document As iTextSharp.text.Document, ByVal rect As iTextSharp.text.Rectangle, ByVal text As String) Implements iTextSharp.text.pdf.IPdfPageEvent.OnGenericTag

        End Sub

        Public Sub OnOpenDocument(ByVal writer As iTextSharp.text.pdf.PdfWriter, ByVal document As iTextSharp.text.Document) Implements iTextSharp.text.pdf.IPdfPageEvent.OnOpenDocument

        End Sub

        Public Sub OnParagraph(ByVal writer As iTextSharp.text.pdf.PdfWriter, ByVal document As iTextSharp.text.Document, ByVal paragraphPosition As Single) Implements iTextSharp.text.pdf.IPdfPageEvent.OnParagraph

        End Sub

        Public Sub OnParagraphEnd(ByVal writer As iTextSharp.text.pdf.PdfWriter, ByVal document As iTextSharp.text.Document, ByVal paragraphPosition As Single) Implements iTextSharp.text.pdf.IPdfPageEvent.OnParagraphEnd

        End Sub

        Public Sub OnSection(ByVal writer As iTextSharp.text.pdf.PdfWriter, ByVal document As iTextSharp.text.Document, ByVal paragraphPosition As Single, ByVal depth As Integer, ByVal title As iTextSharp.text.Paragraph) Implements iTextSharp.text.pdf.IPdfPageEvent.OnSection

        End Sub

        Public Sub OnSectionEnd(ByVal writer As iTextSharp.text.pdf.PdfWriter, ByVal document As iTextSharp.text.Document, ByVal paragraphPosition As Single) Implements iTextSharp.text.pdf.IPdfPageEvent.OnSectionEnd

        End Sub

        Public Sub OnStartPage(ByVal writer As iTextSharp.text.pdf.PdfWriter, ByVal document As iTextSharp.text.Document) Implements iTextSharp.text.pdf.IPdfPageEvent.OnStartPage

        End Sub
    End Class
End Class

答案 1 :(得分:0)

我相信您可以修改PdfTemplate的实例,直到您致电document.close()

  1. 更改页眉/页脚代码以在PdfTemplate内绘制所有内容。
  2. 保存页面之间的最后PdfTemplate
  3. 在致电document.close()之前,重置最后一个页眉和页脚,并按照您最后一页所需的方式绘制它。
  4. PS:在为多个页面绘制完全相同的东西时,使用PdfTemplate非常有效。您只需构建一次模板,然后在需要它的每个页面上重复使用它。然而,在这种特殊情况下,它实际上增加了一点开销,因为你必须为每个页面创建一个,这样你就可以在事后更改最后一个。

    OTOH,如果你在每个页面上都有相同的东西,加上最后一个上面的一些额外的东西,你可以嵌套模板。一个具有Unchanging Stuff,另一个模板只是将所有页面包装在所有页面上,而不是最后一个。在最后一页上,您可以直接添加内容,而不是重置现有内容。

    PPS:IIRC,这就是你如何构建“页面x的y”页脚。所有页面都包含一些“第x页”的直接内容。在close()之前渲染完所有网页后,您可以使用网页计数填写该模板。