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();
}
- Process the output from a
PdfWriter
to abytestream
first with a dummy page count. - Create a
PdfReader
from thatbytestream
, callingPdfReader.getNumberOfPages
to get the actual page count. - 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.