I can't insert something as “Page X of Y” into

2020-04-21 02:35发布

问题:

I am pretty new in iTextSharp and I have the following situation: I am creating a PDF that contains an header and a footer (for the header and footer creation I am using a class that extends PdfPageEventHelper and I have override the OnStartPage() and the OnEndPage() method, it work fine).

Now my problem is that I have to insert as Page X of Y into my footer. Where X**is the **current page number and Y is the total page number. The value of Y is not fixed (because the length of my PDF is not known in advance because it depends depends on the length of the content and can differ from PDF to PDF). How can I handle this situation? (inserting the correct Y value in each footer?)

Searching online I have find this tutorial (that is for Java iText but maybe it is not so different from iTextSharp version): http://itextpdf.com/examples/iia.php?id=104

In this example it create a PDF and its header contains something like Page X of Y.

I am trying to understand this example (and translate it for iTextSharp) but I have some doubts about how it work (and if it is a real solution for my problem).

From what I can understand it perform the following operations:

Into the class that extends PdfPageEventHelper it is declared a PdfTemplate object

PdfTemplate total;

I think that maybe it handles the total pages number that are into my PDF document, but reading the official documentation I have not many information about what exactly do this class: http://api.itextpdf.com/itext/com/itextpdf/text/pdf/PdfTemplate.html

I am trying to do something similar into my class that extends PdfPageEventHelper but I can't do it.

This is my not working code:

public class PdfHeaderFooter : PdfPageEventHelper
{

    // The template with the total number of pages:
    PdfTemplate total;

    private static int numPagina = 1;

    public Image CellImage;
    private string folderImages;
    private string _sourceId;


    public PdfHeaderFooter(string _folderImages, string sourceId)
    {
        folderImages = _folderImages;
        _sourceId = sourceId;

    }


    /* Creates the PdfTemplate that will hold the total number of pages.
     * Write on top of document
     * */
    public override void OnOpenDocument(PdfWriter writer, Document document)
    {

        base.OnOpenDocument(writer, document);

        // (Nobili) Page Number:
        total = writer.DirectContent.CreateTemplate(30, 16);

        //PdfPTable tabFot = new PdfPTable(new float[] { 1F });
        PdfPTable tabFot = new PdfPTable(2);
        tabFot.WidthPercentage = 98;
        tabFot.SpacingAfter = 10F;
        PdfPCell cell;
        //tabFot.TotalWidth = 300F;
        cell = new PdfPCell(new Phrase("Header"));
        tabFot.AddCell(cell);
        tabFot.WriteSelectedRows(0, -1, 150, document.Top, writer.DirectContent);
    }


    // write on end of each page
    public override void OnEndPage(PdfWriter writer, Document document)
    {
        base.OnEndPage(writer, document);

        int pageN = writer.PageNumber;
        String text = "Page " + pageN + " of ";

        //PdfPTable tabFoot = new PdfPTable(new float[] { 1F });
        PdfPTable tabFoot = new PdfPTable(3);
        tabFoot.TotalWidth = document.Right - document.Left;

        tabFoot.DefaultCell.Border = PdfPCell.NO_BORDER;
        tabFoot.DefaultCell.CellEvent = new RoundedBorder();

        PdfPTable innerTable = new PdfPTable(2);
        innerTable.SetWidths(new int[] { 247, 246 });
        innerTable.TotalWidth = document.Right - document.Left;
        innerTable.DefaultCell.Border = PdfPCell.NO_BORDER;
        PdfPCell innerCellLeft = new PdfPCell(new Phrase("Early Warning - Bollettino")) { Border = PdfPCell.NO_BORDER, Padding = 5, MinimumHeight = 20, HorizontalAlignment = Element.ALIGN_LEFT };
        //PdfPCell innerCellRight = new PdfPCell(new Phrase("Pag. " + numPagina + "/5")) { Border = PdfPCell.NO_BORDER, Padding = 5, MinimumHeight = 20, HorizontalAlignment = Element.ALIGN_RIGHT };
        PdfPCell innerCellCenter = new PdfPCell(new Phrase(text)) { Border = PdfPCell.NO_BORDER, Padding = 5, MinimumHeight = 20, HorizontalAlignment = Element.ALIGN_RIGHT };
        PdfPCell innerCellRight = new PdfPCell(Image.GetInstance(total)) { Border = PdfPCell.NO_BORDER, Padding = 5, MinimumHeight = 20, HorizontalAlignment = Element.ALIGN_RIGHT };

        innerTable.AddCell(innerCellLeft);
        innerTable.AddCell(innerCellRight);

        tabFoot.AddCell(innerTable);

        tabFoot.WriteSelectedRows(0, -1, document.Left, document.Bottom, writer.DirectContent);

        numPagina++;
    }


    // write on start of each page
    public override void OnStartPage(PdfWriter writer, Document document)
    {
        base.OnStartPage(writer, document);
        PdfPTable tabHead = new PdfPTable(3);
        tabHead.SetWidths(new int[] { 165, 205, 125 });

        //tabHead.TotalWidth = 460F;
        tabHead.TotalWidth = document.Right - document.Left;        // TotalWidth = 495
        tabHead.WidthPercentage = 98;


        PdfPCell cell1 = new PdfPCell(iTextSharp.text.Image.GetInstance(folderImages + "logoEarlyWarning.png"), true) { Border = PdfPCell.BOTTOM_BORDER };
        tabHead.AddCell(cell1);
        //tabHead.AddCell(new PdfPCell(new Phrase("CELL 1:")) { Border = PdfPCell.BOTTOM_BORDER, Padding = 5, MinimumHeight = 50, PaddingTop = 15, });

        tabHead.AddCell(new PdfPCell(new Phrase("CELL 2:")) { Border = PdfPCell.BOTTOM_BORDER, Padding = 5, MinimumHeight = 50, PaddingTop = 15 });

        if(_sourceId == "NVD")
        {
            iTextSharp.text.Image logo = iTextSharp.text.Image.GetInstance(folderImages + "nvdLogo.png");
            logo.ScalePercent(48f);
            //PdfPCell cell3 = new PdfPCell(iTextSharp.text.Image.GetInstance(folderImages + "nvdLogo.png"), true) { Border = PdfPCell.BOTTOM_BORDER, PaddingBottom = 25 };
            PdfPCell cell3 = new PdfPCell(logo) { Border = PdfPCell.BOTTOM_BORDER, PaddingLeft = 50 };
            tabHead.AddCell(cell3);
        }
        else if(_sourceId == "DeepSight")
        {
            PdfPCell cell3 = new PdfPCell(iTextSharp.text.Image.GetInstance(folderImages + "DSLogo.jpg"), true) { Border = PdfPCell.BOTTOM_BORDER };
            tabHead.AddCell(cell3);
        }
        //tabHead.AddCell(new PdfPCell(new Phrase("CELL 3:")) { Border = PdfPCell.BOTTOM_BORDER, Padding = 5, MinimumHeight = 50, PaddingTop = 15 });


        tabHead.WriteSelectedRows(0, -1, document.Left, document.Top, writer.DirectContent);
    }



    //write on close of document
    public override void OnCloseDocument(PdfWriter writer, Document document)
    {
        base.OnCloseDocument(writer, document);
    }



}

}

I want put in the footer something like the Page X of Y as shown in the tutorial

I tryied to do the following thing:

1) I declared the PdfTemplate total; object as field of my class and I initialize it into my OnOpenDocument() method

 total = writer.DirectContent.CreateTemplate(30, 16);

2) Into my OnEndPage() method I put:

String text = "Page " + pageN + " of ";

and I created the following table to show the Page X of Y

PdfPCell innerCellLeft = new PdfPCell(new Phrase("Early Warning - Bollettino")) { Border = PdfPCell.NO_BORDER, Padding = 5, MinimumHeight = 20, HorizontalAlignment = Element.ALIGN_LEFT };
PdfPCell innerCellCenter = new PdfPCell(new Phrase(text)) { Border = PdfPCell.NO_BORDER, Padding = 5, MinimumHeight = 20, HorizontalAlignment = Element.ALIGN_RIGHT };
            PdfPCell innerCellRight = new PdfPCell(Image.GetInstance(total)) { Border = PdfPCell.NO_BORDER, Padding = 5, MinimumHeight = 20, HorizontalAlignment = Element.ALIGN_RIGHT };

But it don't work and throw me an exception

What could be the problem in my code?

回答1:

You are copy/pasting code without reading the documentation that comes with the examples. Moreover you are completely ignoring the C# version of the examples from my book. I have paid good money to a C# developer to port these examples. It feels as if that money was thrown away. You can find the example you tried to port yourself here: http://tinyurl.com/itextsharpIIA2C05

Error #1: you are adding content in the OnStartPage() method. That is forbidden! This is documented on many places. See for instance this answer copied from page 150 of the official documentation:

FAQ Why is it not advised to add content in the onStartPage() method? You'll remember from section 5.2.4 that iText ignores newPage() calls when the current page is empty. This method is executed — or ignored — when you call it explicitly from your code, but it's also invoked implicitly from within iText on multiple occasions. It's important that it's ignored for empty pages; otherwise you'd end up with plenty of unwanted new pages that are unintentionally left blank. If you add content in an onStartPage() method, there's always a risk of having unwanted pages. Consider it more safe to reserve the onEndPage() method for adding content.

Error #2: you are adding content in the OnOpenDocument() method. Why would that make sense?

Error #3: you create the total object because you want to create a place holder that can be added to each page. Once you know the total number of pages, you want to fill out that number on that place holder. However: I don't see you doing this anywhere. The appropriate place to do this, is obviously in the OnCloseDocument() even. This event is triggered right before the document is closed, so at that moment, the total number of pages is known. This is, as Sherlock Holmes would say, elementary, my dear!