Search code examples
itextitext7

How to add a "Page X of Y" footer in iText 7


I'm trying to figure out how to add a "Page X of Y" footer to each page in a PDF document, which I'm generating using iText 7.

Using an IEventHandler to generate the "Page X" part seems fairly straightforward - it's the "of Y" bit that I'm struggling with. I want to avoid generating the whole document twice in order to find out how many pages it has, as this would be a significant performance hit!

I've found a solution for this in iText 5 here: PDF Page Numbering in Java & iText, but iText 7 is a complete rewrite of iText with a totally different interface and so far I've been unable to find any similar iText 7 examples.


Solution

  • The answer you found for iText 5 references the MovieCountries1 example. This example has been rewritten for iText 7 as Listing_05_20_MovieCountries1. Its pivotal code:

    protected PdfFont bold;
    protected PdfFont italic;
    protected PdfFont normal;
    
    protected PdfFormXObject template;
    
    public void manipulatePdf(String dest) throws IOException, SQLException {
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
        Document doc = new Document(pdfDoc, new PageSize(PageSize.A4), true);
        doc.setMargins(54, 36, 36, 36);
    
        bold = PdfFontFactory.createFont(FontConstants.HELVETICA_BOLD);
        italic = PdfFontFactory.createFont(FontConstants.HELVETICA_OBLIQUE);
        normal = PdfFontFactory.createFont(FontConstants.HELVETICA);
    
        template = new PdfFormXObject(new Rectangle(550, 803, 30, 30));
        PdfCanvas canvas = new PdfCanvas(template, pdfDoc);
    
        HeaderHandler headerHandler = new HeaderHandler();
        pdfDoc.addEventHandler(PdfDocumentEvent.START_PAGE, headerHandler);
    
        ... ADD CONTENT ...
    
        canvas.beginText();
        try {
            canvas.setFontAndSize(PdfFontFactory.createFont(FontConstants.HELVETICA), 12);
        } catch (IOException e) {
            e.printStackTrace();
        }
        canvas.moveText(550, 803);
        canvas.showText(Integer.toString(pdfDoc.getNumberOfPages()));
        canvas.endText();
        canvas.release();
    
        doc.close();
    }
    
    public class HeaderHandler implements IEventHandler {
        protected String country;
    
        @Override
        public void handleEvent(Event event) {
            PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
            PdfPage page = docEvent.getPage();
            int pageNum = docEvent.getDocument().getPageNumber(page);
            PdfCanvas canvas = new PdfCanvas(page);
            canvas.beginText();
            try {
                canvas.setFontAndSize(PdfFontFactory.createFont(StandardFonts.HELVETICA), 12);
            } catch (IOException e) {
                e.printStackTrace();
            }
            canvas.moveText(34, 803);
            canvas.showText(country);
            canvas.moveText(450, 0);
            canvas.showText(String.format("Page %d of", pageNum));
            canvas.endText();
            canvas.stroke();
            canvas.addXObject(template, 0, 0);
            canvas.release();
        }
    
        public void setHeader(String country) {
            this.country = country;
        }
    }
    

    You'll find rewrites of many other samples there, too.


    As @Bruno remarked in a comment, there even is a slightly different example which has been genuinely created for iText 7 (in contrast to the example above which is the port of an iText 5 example).

    It's an example accompanying the chapter 7 of the iText 7: building blocks tutorial. It uses showTextAligned() to make sure the "Page X of" nicely matches with the "Y", no matter how many digits X and Y have, cf. its end-of-page event listener method:

    public void handleEvent(Event event) {
        PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
        PdfDocument pdf = docEvent.getDocument();
        PdfPage page = docEvent.getPage();
        int pageNumber = pdf.getPageNumber(page);
        Rectangle pageSize = page.getPageSize();
        PdfCanvas pdfCanvas = new PdfCanvas(
            page.newContentStreamBefore(), page.getResources(), pdf);
        Canvas canvas = new Canvas(pdfCanvas, pdf, pageSize);
        Paragraph p = new Paragraph()
            .add("Page ").add(String.valueOf(pageNumber)).add(" of");
        canvas.showTextAligned(p, x, y, TextAlignment.RIGHT);
        pdfCanvas.addXObject(placeholder, x + space, y - descent);
        pdfCanvas.release();
    }
    

    (C07E03_PageXofY.java, event handler class PageXofY)