简体   繁体   English

如何使用iTextSharp动态生成的PDF在某些页面上做不同的事情?

[英]How to do something different on some pages in a dynamically generated PDF generated with iTextSharp?

I am dynamically generating a PDF document with iTextSharp. 我正在使用iTextSharp动态生成PDF文档。 I don't know how many pages it will contain. 我不知道它将包含多少页。 I have managed to create headers and footers on all pages by overriding OnStartPage and OnEndPage on PdfPageEventHelper. 通过覆盖PdfPageEventHelper的OnStartPage和OnEndPage,我设法在所有页面上创建了页眉和页脚。 However, with this approach the header is the same on all pages and the footer is the same on all pages. 但是,使用这种方法时,所有页面上的页眉都相同,而所有页面上的页脚均相同。 I need to be more dynamic: I need to show a different footer on the last page. 我需要更加动态:我需要在最后一页上显示不同的页脚。

When I am in the OnEndPage method I know the pagenumber of the page, but I don't know whether it is the last. 当我使用OnEndPage方法时,我知道页面的页码,但是我不知道它是否是最后一个。 When I am in the OnCloseDocument method I know the total number of pages, but I cannot from here "delete" or "remove" or change the footer that was added to the last page by OnEndPage. 当我使用OnCloseDocument方法时,我知道页面的总数,但是我不能从此处“删除”或“删除”或更改由OnEndPage添加到最后一页的页脚。

So you've got a main loop of code that's creating pages and adding content, right? 因此,您有一个主要的代码循环来创建页面和添加内容,对吗? Once that content finishes can you set a global flag that OnEndPage looks for? 内容完成后,您可以设置OnEndPage寻找的全局标志吗?

The code below (in VB.Net, sorry) creates a class (so we can pass it around by reference) with a single boolean variable that once we finish our main processing loop we set to true so that OnEndPage knows to do something different. 下面的代码(在VB.Net中,对不起)使用单个布尔变量创建一个类(以便我们可以通过引用传递它),一旦完成主处理循环,我们将其设置为true以便OnEndPage知道可以做一些不同的事情。 Sorry for the verbose IPdfPageEvent , VB requires all methods to be declared even if you don't use them. 抱歉,冗长的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

I believe you can modify instances of PdfTemplate until you call document.close() . 我相信您可以修改PdfTemplate实例,直到调用document.close()为止。

  1. Change your header/footer code to draw everything inside a PdfTemplate . 更改页眉/页脚代码以在PdfTemplate绘制所有内容。
  2. Save the last PdfTemplate between pages. 保存页面之间的最后一个PdfTemplate
  3. Just before calling document.close() , reset that last header-and-or-footer and draw it the way you need it for that last page. 就在调用document.close()之前,重置最后一个页眉和页脚,并根据您最后一页的需要绘制它。

PS: Using a PdfTemplate can be really efficient when drawing Exactly The Same Thing to multiple pages. PS:当将“完全相同的东西”绘制到多个页面时,使用PdfTemplate会非常有效。 You build the template once, then reuse it on every page that needs it. 您只需构建一次模板,然后在需要它的每个页面上重复使用它。 In this particular case however, it actually adds a little overhead because you have to create one for each page just so you can change the last one after the fact. 但是,在这种情况下,实际上会增加一些开销,因为您必须为每个页面创建一个页面,以便您可以在事后更改最后一个页面。

OTOH, if you have largely the same stuff on every page, plus a little extra stuff on the last one, you can nest templates. OTOH,如果每个页面上的内容大体相同,而最后一页上又有一些额外的内容,则可以嵌套模板。 One that has Unchanging Stuff, and another template that simply wraps that one on all pages but the last. 一个模板具有不变的内容,另一个模板仅将那个模板包装在除最后一页之外的所有页面上。 On the last page, rather than resetting the existing content, you could simply add to it. 在最后一页上,您不必添加现有内容,而只需重置即可。

PPS: IIRC, this is how you build "page x of y" footers. PPS:IIRC,这是您构建“ y的第x页”页脚的方法。 All the pages contain some direct content with "page x of ". 所有页面都包含一些直接内容,其中“页面x为”。 Once you've rendered all your pages, prior to close() , you fill in that template with the page count. 呈现完所有页面后,在close()之前,您需要在页面数量中填充该模板。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何PDF调整rdlc和itextsharp生成的大小 - How to PDF Resize generated by rdlc and itextsharp 如何使用iTextSharp将页面页脚添加到PDF文档中以横向生成页面 - how to add page footer to PDF document using iTextSharp for pages generated in landscape 用挪威语生成的Itextsharp pdf在某些文本后添加底部填充 - Itextsharp pdf generated with Norwegian adds bottom padding after some text iTextSharp生成的PDF:如何将pdf发送给客户端并添加提示? - iTextSharp generated PDF: How to send the pdf to the client and add a prompt? 如何在使用HTML表格生成的itextsharp pdf中添加新页面 - How to add new page in itextsharp pdf generated using html table 使用iTextSharp将PDF附加到生成的PDF - Appending PDFs to generated PDF using iTextSharp iTextSharp生成的PDF在浏览器中有效,但下载后不起作用 - iTextSharp generated PDF works in browser but not after download 使用iTextSharp生成的PDF总是在关闭时提示保存更改。 使用非Acrobat PDF阅读器查看时缺少页面 - PDF generated with iTextSharp always prompts to save changes when closing. And has missing pages when viewed with non-Acrobat PDF readers 计算动态生成的页面数 - Count the number of dynamically generated pages 使用 iTextSharp 将不同大小的页面添加到 PDF - Adding different sized pages to PDF using iTextSharp
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM