35

It seems rather simple, but I can't find something like getPageCount() in the API. I can get it to return the current page, but not the total number of pages. Perhaps I'm missing it?

I would like to somehow be able to print 'Page 1 of 9' at the top of every page, where '1' of course is the current page number.

mkautzm
  • 1,086
  • 2
  • 18
  • 34

5 Answers5

33

Make sure to include the using MigraDoc.DocumentObjectModel; statement in your class.

Document document = new Document();
Section section = document.AddSection();

Paragraph paragraph = new Paragraph();
paragraph.AddText("Page ");
paragraph.AddPageField();
paragraph.AddText(" of ");
paragraph.AddNumPagesField();

section.Headers.Primary.Add(paragraph);
Kidquick
  • 1,102
  • 12
  • 13
  • 2
    What is this `MigraDoc` and where do I get it? I'm using `PdfSharp`, like the questions states. I don't have a `Document` only a `PdfDocument` – slow Oct 12 '18 at 09:17
  • 1
    @sLw MigraDoc is a layer on top of PDFsharp which provides an object-oriented approach to creating PDFs. Simplifies PDF design IMO. See pdfsharp.net for more info. – Kidquick Apr 22 '19 at 02:47
30

With PDFsharp it's up to you.

I presume you are using MigraDoc: With MigraDoc you can add a page header. Add paragraph.AddPageField() for the current page number and paragraph.AddNumPagesField() for the total page count.

Sample that uses AddPageField

Code snippet from the sample:

// Create a paragraph with centered page number. See definition of style "Footer".
Paragraph paragraph = new Paragraph();
paragraph.AddTab();
paragraph.AddPageField();

// Add paragraph to footer for odd pages.
section.Footers.Primary.Add(paragraph);
// Add clone of paragraph to footer for odd pages. Cloning is necessary because an object must
// not belong to more than one other object. If you forget cloning an exception is thrown.
section.Footers.EvenPage.Add(paragraph.Clone());

Code snippet that sets the tab stop (assuming DIN A 4 with a body with of 16 cm):

style = document.Styles[StyleNames.Footer]; 
style.ParagraphFormat.AddTabStop("8cm", TabAlignment.Center); 

Both snippets taken from the linked site. Sample code is also available for download.

  • Sample showed at this page doesn't work well. I mean that page number doesn't change. – Marek Bar Apr 30 '14 at 20:37
  • 2
    @Marek Bar: AddNumPagesField adds the number of pages in the document (and does not change between pages), AddPageField adds the current page number and changes from page to page. – I liked the old Stack Overflow May 05 '14 at 12:20
  • @PDFsharpTeam... if I want to display page number ONLY if the PDF is MORE than a page long... how should I do it? Now, my PDF display "Pag: 1" even if I have one page total. – Romias Dec 20 '14 at 03:52
  • @Romias: In the first run create the document for the most likely case (e.g. without footer if a single page is more likely than multiple pages). If the PDF is not as expected (e.g. more than one page) then throw it away and create a new document with footer. Or always create it with footer and use PDFsharp to draw a white rectangle over the footer if it is a single page (that's a hack). Or always create it without footer and use PDFsharp to draw the footer if needed. – I liked the old Stack Overflow Jan 12 '15 at 09:31
  • Works perfectly :) – FranzHuber23 Mar 07 '19 at 09:05
27

I know this question is old and has an accepted answer, however the question comes up among the first when searching for a PDFsharp solution.

For the record, achieving this in PDFsharp is easy. The PdfDocument class, found under the PdfSharp.Pdf namespace contains a collection of pages (PdfDocument.Pages). All you have to do is iterate through the collection and add the page counter somewhere on every page, using a XGraphics object, that you can instantiate using XGraphics.FromPdfPage(PdfPage).

using PdfSharp.Pdf; // PdfDocument, PdfPage
using PdfSharp.Drawing; // XGraphics, XFont, XBrush, XRect
                        // XStringFormats

// Create a new PdfDocument.
PdfDocument document = new PdfDocument();
// Add five pages to the document.
for(int i = 0; i < 5; ++i)
    document.AddPage();

// Make a font and a brush to draw the page counter.
XFont font = new XFont("Verdana", 8);
XBrush brush = XBrushes.Black;

// Add the page counter.
string noPages = document.Pages.Count.ToString();
for(int i = 0; i < document.Pages.Count; ++i)
{
    PdfPage page = document.Pages[i];

    // Make a layout rectangle.
    XRect layoutRectangle = new XRect(0/*X*/, page.Height-font.Height/*Y*/, page.Width/*Width*/, font.Height/*Height*/);

    using (XGraphics gfx = XGraphics.FromPdfPage(page))
    {
        gfx.DrawString(
            "Page " + (i+1).ToString() + " of " + noPages,
            font,
            brush,
            layoutRectangle,
            XStringFormats.Center);
    }
}

It's worth noting that if a XGraphics object already exists for a given page, before creating a new one, the old one needs to be disposed. This would fail:

PdfDocument document = new PdfDocument();
PdfPage page = document.AddPage();

XGraphics gfx1 = XGraphics.FromPage(page);
XGraphics gfx2 = XGraphics.FromPage(page);
DAAlex
  • 446
  • 5
  • 9
0

It is worth noting that AddSectionPagesField() also exists. In this way 'Y' will be the number of pages of the section instead of the number of pages of the entire document.

It finds its use when you generate many different documents for one print and you want to separate page counting. I hope it is understandable.

So then you can also use:

            Paragraph paragraph = new Paragraph();
            paragraph.AddText("Page");
            paragraph.AddPageField();
            paragraph.AddText(" of ");
            paragraph.AddSectionPagesField();

            // Add paragraph to header for odd pages.
            section.Headers.Primary.Add(paragraph);
            // Add clone of paragraph to header for odd pages. Cloning is necessary because an object must
            // not belong to more than one other object. If you forget cloning an exception is thrown.
            section.Headers.EvenPage.Add(paragraph.Clone());

Similarly just for footer use:

            section.Footers.Primary.Add(paragraph);
            section.Footers.EvenPage.Add(paragraph.Clone());
Kamil Z
  • 181
  • 12
-2

here's how you can fix it

        Paragraph foot = sec.Footers.Primary.AddParagraph();
        foot.AddText("Page ");
        foot.AddPageField();
        foot.AddText(" of ");
        foot.AddNumPagesField();
Chamin Wickramarathna
  • 1,672
  • 2
  • 20
  • 34