Mick Byrne
Mick Byrne

Reputation: 14484

iTextSharp - Don't display page numbers if only one page

I have a PDF generated using iTextSharp that displays a "Page 1/4" etc. thing in the footer. This all works fine and is implemented using a PdfTemplate that is set in the OnEndPage() method with the total number of pages added in the OnCloseDocument() method.

What I would like to do is remove this if there is only one page in the document. I've tried this in my OnCloseDocument() method, but it doesn't actually remove the template:

        public override void OnCloseDocument(PdfWriter writer, Document document)
        {
            base.OnCloseDocument(writer, document);

            if (writer.PageNumber >= 3)
            {
                template.BeginText();
                template.SetFontAndSize(f_cn, CocService.footerFont.Size);
                template.SetTextMatrix(0, 0);
                template.ShowText("" + (writer.PageNumber - 1));
                template.EndText();
            }
            else
            {
                template.Reset();
            }
        }

Just for reference, here's the relevant code from the OnEndPage() method:

        public override void OnEndPage(PdfWriter writer, Document document)
        {
            base.OnEndPage(writer, document);

            int pageN = writer.PageNumber;
            String text = "Page " + pageN.ToString() + "/";

            float len = f_cn.GetWidthPoint(text, CocService.footerFont.Size);
            iTextSharp.text.Rectangle pageSize = document.PageSize;
            cb.SetRGBColorFill(100, 100, 100);
            cb.BeginText();
            cb.SetFontAndSize(f_cn, CocService.footerFont.Size);
            cb.SetTextMatrix(document.LeftMargin+520, pageSize.GetBottom(document.BottomMargin)+33);
            cb.ShowText(text);
            cb.EndText();
            cb.AddTemplate(template, document.LeftMargin + 520 + len, pageSize.GetBottom(document.BottomMargin)+33);
        }

Upvotes: 2

Views: 4239

Answers (2)

Bruno Lowagie
Bruno Lowagie

Reputation: 77528

You are already writing text to the content stream in your onEndPage() method, and there's no way to remove that after the fact because that stream may already have been sent to the OutputStream.

The best way to avoid having any page numbers on a document if there's only one page, is to add page numbers in a second go. Take a look at the TwoPasses example, especially where it says "SECOND PASS". IMO, this is the most elegant way to solve your problem. Ask the reader for the number of pages. If it's 1, do nothing. If it's more, add page X of Y.

By the way: for the C# port of the examples, go to http://tinyurl.com/itextsharpIIA2C06

Upvotes: 1

Mick Byrne
Mick Byrne

Reputation: 14484

The solution I ended up going with was adding a separate PdfTemplate object to each page, then setting all the page numbers (or leaving them out altogether) in the OnCloseDocument() method. I thought this was pretty elegant too. Here's the essential code:

    // Inner class for dealing with the page numbering
    class CocPdfEventHelper : PdfPageEventHelper
    {
        List<PdfTemplate> pageNumberTemplates = new List<PdfTemplate>();

        public override void OnEndPage(PdfWriter writer, Document document)
        {
            base.OnEndPage(writer, document);

            // Add a unique (empty) template for each page here
            PdfTemplate t = writer.DirectContent.CreateTemplate(180, 50);
            pageNumberTemplates.Add(t);
            writer.DirectContent.AddTemplate(t, document.LeftMargin + 520, document.PageSize.GetBottom(document.BottomMargin) + 33);
        }

        public override void OnCloseDocument(PdfWriter writer, Document document)
        {
            base.OnCloseDocument(writer, document);

            // Only bother if there is more than 1 page
            if (writer.PageNumber >= 3)
            {
                int count = 1;
                foreach (PdfTemplate template in pageNumberTemplates)
                {
                    template.BeginText();
                    template.SetFontAndSize(f_cn, CocService.footerFont.Size);
                    template.SetRGBColorFill(100, 100, 100);
                    template.SetTextMatrix(0,0);
                    template.ShowText("Page " + count + " of " + (writer.PageNumber - 1));
                    template.EndText();
                    count++;
                }
            }
        }
    }

Upvotes: 4

Related Questions