[英]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()
为止。
PdfTemplate
. PdfTemplate
绘制所有内容。 PdfTemplate
between pages. PdfTemplate
。 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.