How to add total page number on every page with iText?

You can create a class that inherits from PdfPageEventHelper then override theses two functions like this :

Imports System.Collections.Generic
Imports System.Text

Imports iTextSharp.text.pdf
Imports iTextSharp.text

Namespace PDF_EnteteEtPiedDePage
    Public Class EnteteEtPiedDePage
        Inherits PdfPageEventHelper
        ' This is the contentbyte object of the writer
        Private cb As PdfContentByte

        ' we will put the final number of pages in a template
        Private template As PdfTemplate

        ' this is the BaseFont we are going to use for the header / footer
        Private bf As BaseFont = Nothing

        ' This keeps track of the creation time
        Private PrintTime As DateTime = DateTime.Now

        ' we override the onOpenDocument method
        Public Overrides Sub OnOpenDocument(writer As PdfWriter, document As Document)
            Try
                PrintTime = DateTime.Now
                bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED)
                cb = writer.DirectContent
                template = cb.CreateTemplate(50, 50)
            Catch de As DocumentException
            Catch ioe As System.IO.IOException
            End Try
        End Sub

        Public Overrides Sub OnStartPage(writer As PdfWriter, document As Document)
            MyBase.OnStartPage(writer, document)

            Dim pageSize As Rectangle = document.PageSize

        End Sub

        Public Overrides Sub OnEndPage(writer As PdfWriter, document As Document)
            MyBase.OnEndPage(writer, document)

            Dim pageN As Integer = writer.PageNumber
            Dim text As [String] = "Page " & pageN & " de "
            Dim len As Single = bf.GetWidthPoint(text, 8)

            Dim pageSize As Rectangle = document.PageSize

            cb.SetRGBColorFill(100, 100, 100)

            cb.BeginText()
            cb.SetFontAndSize(bf, 8)
            cb.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetBottom(30))
            cb.ShowText(text)
            cb.EndText()

            cb.AddTemplate(template, pageSize.GetLeft(40) + len, pageSize.GetBottom(30))

            cb.BeginText()
            cb.SetFontAndSize(bf, 8)
            cb.ShowTextAligned(PdfContentByte.ALIGN_RIGHT, "Imprimé le : " & PrintTime.ToShortDateString() & " à " & PrintTime.ToShortTimeString, pageSize.GetRight(40), pageSize.GetBottom(30), 0)
            cb.EndText()
        End Sub

        Public Overrides Sub OnCloseDocument(writer As PdfWriter, document As Document)
            MyBase.OnCloseDocument(writer, document)

            template.BeginText()
            template.SetFontAndSize(bf, 8)
            template.SetTextMatrix(0, 0)
            template.ShowText("" & Convert.ToString((writer.PageNumber - 1)))
            template.EndText()
        End Sub

    End Class
End Namespace

Then after that just set the value of your pdfwriter PageEvent like this :

Dim PageEventHandler = New EnteteEtPiedDePage()
            aPdfWriter.PageEvent = PageEventHandler

Here is the code I used. It does not add to much overhead to write the pages to the output.

outputStream = new ByteArrayOutputStream();
output = new DataOutputStream(outputStream);
document = new Document();
writer = PdfWriter.getInstance(document, output);
document.open();
contentByte = writer.getDirectContent();
....add stuff
document.close();
writer.close();
byte[] output = outputStream.toByteArray();
PdfReader reader = new PdfReader(output);
//reset the output
outputStream = new ByteArrayOutputStream();
output = new DataOutputStream(outputStream);
document = new Document();
writer = PdfWriter.getInstance(document, output);
document.open();
PdfStamper stamper = new PdfStamper(reader, outputStream);
//add the pages
for (int i = 1; i <= pageCount; i++)
{
    contentByte = stamper.getOverContent(i);
    addParagraph("Page " + i + " of " + pageCount, new Point(500, 30), boldTextFont);  // my own paragraph font
}
stamper.close();

Here is a handy Function! (Based on Milhous's approach) (this uses itext version 4.1.6.0)

public static byte[] AddPageNumbers(byte[] pdf)
        {
            PdfReader reader = new PdfReader(pdf);
            var Pages = reader.NumberOfPages;
            MemoryStream ms = new MemoryStream();

            PdfStamper stamper = new PdfStamper(reader, ms);
            for (int i = 1; i <= Pages; i++)
            {
                PdfContentByte overContent;
                Font Signature = FontFactory.GetFont("Calibiri", 9, iTextSharp.text.Font.NORMAL, Color.BLACK);
                overContent = stamper.GetOverContent(i);
                var helv = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
                overContent.SaveState();
                overContent.BeginText();
                overContent.SetFontAndSize(helv, 10.0f);
                overContent.SetTextMatrix(PageSize.LETTER.Width / 2 - 20, PageSize.LETTER.Height - (PageSize.LETTER.Height - 20));
                overContent.ShowText("Page " + (i) + " of " + Pages);
                overContent.EndText();
                overContent.RestoreState();
            }
            stamper.Close();            
            return ms.ToArray();
        }

  1. Process the output from a PdfWriter to a bytestream first with a dummy page count.
  2. Create a PdfReader from that bytestream, calling PdfReader.getNumberOfPages to get the actual page count.
  3. Recreate the PDF output, knowing what the page count will be, changing the footer accordingly.

It's messy, but there's no easy way to know the page count without a two-pass approach. See the example code for details on manipulating PDFs.

Tags:

Java

Itext