Skip to main content

How to Add Page Numbers to PDF in Java (Step-by-Step)

 Page numbers are a small detail, but they become important in reports, contracts, manuals, and other multi-page PDFs. They make printed documents easier to navigate and give reviewers a simple way to refer to a specific page.

When PDFs are generated or processed in a Java application, adding page numbers manually is not practical. A better approach is to add them programmatically after the document has been created or assembled.

In this article, we'll use Spire.PDF for Java to add dynamic page numbers in the format Page 1 of 10 to an existing PDF.


Install Spire.PDF for Java

If you use Maven, add the repository and Spire.PDF dependency to your pom.xml:

<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.com/nexus/content/groups/public/</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.pdf</artifactId>
        <version>12.8.1</version>
    </dependency>
</dependencies>

Add "Page X of Y" to a PDF in Java

Spire.PDF for Java provides three useful classes for dynamic page numbering:

  • PdfPageNumberField represents the current page number.
  • PdfPageCountField represents the total number of pages.
  • PdfCompositeField combines these values into text such as Page 2 of 10.

This means you don't need to create a different page-number string for every page manually.

The following example adds a centered page number near the bottom of every page:

import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import com.spire.pdf.automaticfields.PdfCompositeField;
import com.spire.pdf.automaticfields.PdfPageCountField;
import com.spire.pdf.automaticfields.PdfPageNumberField;
import com.spire.pdf.graphics.PdfBrush;
import com.spire.pdf.graphics.PdfBrushes;
import com.spire.pdf.graphics.PdfTrueTypeFont;

import java.awt.Font;
import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;

public class AddPageNumbers {

    public static void main(String[] args) {

        // Load the PDF document
        PdfDocument document = new PdfDocument();
        document.loadFromFile("input.pdf");

        // Set the font and color of the page number
        PdfTrueTypeFont font = new PdfTrueTypeFont(
                new Font("Arial", Font.PLAIN, 10), true);
        PdfBrush brush = PdfBrushes.getBlack();

        // Create fields for the current page number and total page count
        PdfPageNumberField pageNumberField = new PdfPageNumberField();
        PdfPageCountField pageCountField = new PdfPageCountField();

        // Combine the fields into "Page X of Y"
        PdfCompositeField pageNumber = new PdfCompositeField(
                font,
                brush,
                "Page {0} of {1}",
                pageNumberField,
                pageCountField
        );

        // Add the page number to each page
        for (int i = 0; i < document.getPages().getCount(); i++) {

            PdfPageBase page = document.getPages().get(i);
            Dimension2D pageSize = page.getSize();

            // Measure the displayed text so it can be centered
            String text = String.format(
                    "Page %d of %d",
                    i + 1,
                    document.getPages().getCount()
            );

            Dimension2D textSize = font.measureString(text);

            // Calculate the position at the bottom center of the page
            double x = (pageSize.getWidth() - textSize.getWidth()) / 2;
            double y = pageSize.getHeight() - 30;

            // Draw the page number
            pageNumber.setLocation(
                    new Point2D.Float((float) x, (float) y)
            );
            pageNumber.draw(page.getCanvas());
        }

        // Save the result
        document.saveToFile("output.pdf");
        document.dispose();
    }
}

The implementation is fairly short, but there are a few details worth understanding.

Step 1: Load the Existing PDF

Start by creating a PdfDocument object and loading the source PDF:

PdfDocument document = new PdfDocument();
document.loadFromFile("input.pdf");

This approach works for an existing PDF as well as a document generated earlier in the same application. The page-numbering code only needs to run before the final PDF is saved.

Step 2: Define the Page Number Appearance

Next, create a font and brush:

PdfTrueTypeFont font = new PdfTrueTypeFont(
        new Font("Arial", Font.PLAIN, 10), true);

PdfBrush brush = PdfBrushes.getBlack();

These settings control the font, size, style, and color of the page number.

For most reports, a relatively small font works well in the footer. You can change the font and size to match the rest of the document.

If the application runs on Linux or a server, make sure the font specified in the code is available in that environment. Otherwise, use a font that is installed on the target system.

Step 3: Create Dynamic Page Number Fields

Instead of calculating the page number and total page count yourself, create two automatic fields:

PdfPageNumberField pageNumberField = new PdfPageNumberField();
PdfPageCountField pageCountField = new PdfPageCountField();

PdfPageNumberField supplies the current page number, while PdfPageCountField supplies the total number of pages. Spire.PDF provides these fields specifically for dynamic information added to PDF pages.

They can then be combined with PdfCompositeField:

PdfCompositeField pageNumber = new PdfCompositeField(
        font,
        brush,
        "Page {0} of {1}",
        pageNumberField,
        pageCountField
);

Here, {0} is replaced by the current page number and {1} by the total page count.

For an eight-page PDF, the result will look like:

Page 1 of 8
Page 2 of 8
Page 3 of 8
...
Page 8 of 8

This is more convenient than preparing a separate string for every page, especially when the final page count is not known in advance.

Step 4: Process Each Page Separately

Next, iterate through the PDF:

for (int i = 0; i < document.getPages().getCount(); i++) {

    PdfPageBase page = document.getPages().get(i);
    Dimension2D pageSize = page.getSize();

    // ...
}

The page size is read inside the loop instead of assuming that every page has identical dimensions.

That matters when a PDF contains a mix of portrait and landscape pages or pages with different sizes. Each page can then have its page-number position calculated independently.

Step 5: Center the Page Number at the Bottom

To center the page number properly, first measure the text that will appear on the current page:

String text = String.format(
        "Page %d of %d",
        i + 1,
        document.getPages().getCount()
);

Dimension2D textSize = font.measureString(text);

Then calculate its coordinates:

double x = (pageSize.getWidth() - textSize.getWidth()) / 2;
double y = pageSize.getHeight() - 30;

The X coordinate centers the text horizontally, while the Y coordinate places it near the bottom of the page.

For existing PDFs, Spire.PDF uses a coordinate system whose origin is at the top-left corner. X increases to the right and Y increases downward, which is why a value close to the page height places the page number near the footer.

Finally, set the position and draw the field:

pageNumber.setLocation(
        new Point2D.Float((float) x, (float) y)
);

pageNumber.draw(page.getCanvas());

Because the position is calculated for each page, the page number remains centered even when page dimensions vary.

Change the Page Number Format

The displayed format is controlled by the format string passed to PdfCompositeField.

For example:

"Page {0}"

produces:

Page 1
Page 2
Page 3

For a shorter style, use:

"{0} / {1}"

which produces:

1 / 10

You can also combine page numbers with fixed footer text:

"Project Report | Page {0} of {1}"

The dynamic fields remain the same, so changing the format does not require changing the rest of the page-numbering logic.

Make Sure the Footer Has Enough Space

When adding page numbers to an existing PDF, check whether the bottom of the page already contains text, tables, signatures, or other content.

Drawing a page number does not automatically create extra footer space. If the original content already extends close to the bottom edge, the page number may overlap it.

In that case, adjust the Y coordinate:

double y = pageSize.getHeight() - 30;

to place the page number in a clearer area.

If you also control how the PDF is originally generated, reserving some footer space from the beginning is usually a better solution.

Conclusion

Adding page numbers programmatically is useful when reports, contracts, manuals, or other PDFs are generated in batches or assembled dynamically.

With Spire.PDF for Java, PdfPageNumberField and PdfPageCountField provide the current page number and total page count, while PdfCompositeField combines them into formats such as Page X of Y.

By calculating the position for each page, the same approach also works with PDFs that contain different page sizes or orientations. From there, the footer can be further customized with different formats, fonts, positions, or additional text.

Comments

Popular posts from this blog

3 Ways to Generate Word Documents from Templates in Java

A template is a document with pre-applied formatting like styles, tabs, line spacing and so on. You can quickly generate a batch of documents with the same structure based on the template. In this article, I am going to show you the different ways to generate Word documents from templates programmatically in Java using Free Spire.Doc for Java library. Prerequisite First of all, you need to add needed dependencies for including Free Spire.Doc for Java into your Java project. There are two ways to do that. If you use maven, you need to add the following code to your project’s pom.xml file. <repositories>               <repository>                   <id>com.e-iceblue</id>                   <name>e-iceblue</name>...

Insert and Extract OLE objects in Word in Java

You can use OLE (Object Linking and Embedding) to include content from other programs, such as another Word document, an Excel or PowerPoint document to an existing Word document. This article demonstrates how to insert and extract embedded OLE objects in a Word document in Java by using Free Spire.Doc for Java API.   Add dependencies First of all, you need to add needed dependencies for including Free Spire.Doc for Java into your Java project. There are two ways to do that. If you use maven, you need to add the following code to your project’s pom.xml file.     <repositories>               <repository>                   <id>com.e-iceblue</id>                   <name>e-iceblue</name>    ...

Simple Java Code to Convert Excel to PDF in Java

This article demonstrates a simple solution to convert an Excel file to PDF in Java by using free Excel API – Free Spire.XLS for Java . The following examples illustrate two possibilities to convert Excel to PDF:      Convert the whole Excel file to PDF     Convert a particular Excel Worksheet to PDF Before start with coding, you need to Download Free Spire.XLS for Java package , unzip it and import Spire.Xls.jar file from the lib folder in your project as a denpendency. 1. Convert the whole Excel file to PDF Spire.XLS for Java provides saveToFile method in Workbook class that enables us to easily save a whole Excel file to PDF. import com.spire.xls.FileFormat; import com.spire.xls.Workbook; public class ExcelToPDF {     public static void main(String[] args){         //Create a Workbook         Workbook workbook = new Workbook();   ...