Как сделать что-то другое на некоторых страницах в динамически генерируемом PDF, сгенерированном с помощью iTextSharp? - PullRequest
1 голос
/ 21 марта 2011

Я динамически генерирую PDF-документ с помощью iTextSharp. Я не знаю, сколько страниц он будет содержать. Мне удалось создать верхние и нижние колонтитулы на всех страницах путем переопределения OnStartPage и OnEndPage для PdfPageEventHelper. Однако при таком подходе верхний колонтитул одинаков для всех страниц, а нижний колонтитул одинаков для всех страниц. Мне нужно быть более динамичным: мне нужно показать другой нижний колонтитул на последней странице.

Когда я в методе OnEndPage, я знаю номер страницы, но я не знаю, последний ли это. Когда я использую метод OnCloseDocument, я знаю общее количество страниц, но я не могу отсюда «удалить» или «удалить» или изменить нижний колонтитул, который был добавлен на последнюю страницу с помощью OnEndPage.

Ответы [ 2 ]

0 голосов
/ 21 марта 2011

Полагаю, вы можете изменять экземпляры PdfTemplate, пока не наберете document.close().

  1. Измените код верхнего / нижнего колонтитула, чтобы нарисовать все внутри PdfTemplate.
  2. Сохранить последние PdfTemplate между страницами.
  3. Непосредственно перед вызовом document.close(), сбросьте этот последний верхний и нижний колонтитулы и нарисуйте его так, как вам нужно для этой последней страницы.

PS: использование PdfTemplate может быть действительно эффективным при рисовании точно так жеДело в нескольких страницах.Вы создаете шаблон один раз, а затем повторно используете его на каждой странице, которая нуждается в нем.В данном конкретном случае, однако, это фактически добавляет немного накладных расходов, потому что вы должны создать один для каждой страницы, просто чтобы вы могли изменить последний после факта.

OTOH, если у вас есть в основном одинаковые вещи на каждомстраница, плюс немного дополнительной информации о последней, вы можете вкладывать шаблоны.Тот, у которого есть Unchanging Stuff, и другой шаблон, который просто оборачивает его на всех страницах, кроме последней.На последней странице вместо того, чтобы сбрасывать существующий контент, вы можете просто добавить к нему.

PPS: IIRC, именно так вы строите нижние колонтитулы «страница x из y».Все страницы содержат некоторый прямой контент с «страницей x из».После того, как вы отобразили все свои страницы, до close(), вы заполняете этот шаблон количеством страниц.

0 голосов
/ 21 марта 2011

Итак, у вас есть основной цикл кода, который создает страницы и добавляет контент, верно? Как только содержимое закончится, вы можете установить глобальный флаг, который ищет 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
...