Search code examples
pythonpdfreportlabpage-numberingtableofcontents

Properly add page numbers and total number of pages to PDF using ReportLab


I am trying to create a document that has page numbering of the format "Page x of y". I have tried the NumberedCanvas approach (http://code.activestate.com/recipes/576832/ and also from the forums https://groups.google.com/forum/#!topic/reportlab-users/9RJWbrgrklI) but that conflicts with my clickable Table of Contents (https://www.reportlab.com/snippets/13/).

I understood from this post http://two.pairlist.net/pipermail/reportlab-users/2002-May/000020.html that it may be possible using forms, but examples on this are very scarce and uninformative. Does anybody have any idea on how this can be implemented using forms (or fixing the NumberedCanvas approach?)


Solution

  • This page (http://www.blog.pythonlibrary.org/2013/08/12/reportlab-how-to-add-page-numbers/) explains a good way to do it. I made some changes to make better use of inheritance.

    It creates a new Class that inherits from ReportLab Canvas class.

    This is my modified code:

    from reportlab.lib.units import mm
    from reportlab.pdfgen.canvas import Canvas
    
    
    class NumberedPageCanvas(Canvas):
        """
        http://code.activestate.com/recipes/546511-page-x-of-y-with-reportlab/
        http://code.activestate.com/recipes/576832/
        http://www.blog.pythonlibrary.org/2013/08/12/reportlab-how-to-add-page-numbers/
        """
    
        def __init__(self, *args, **kwargs):
            """Constructor"""
            super().__init__(*args, **kwargs)
            self.pages = []
    
        def showPage(self):
            """
            On a page break, add information to the list
            """
            self.pages.append(dict(self.__dict__))
            self._startPage()
    
        def save(self):
            """
            Add the page number to each page (page x of y)
            """
            page_count = len(self.pages)
    
            for page in self.pages:
                self.__dict__.update(page)
                self.draw_page_number(page_count)
                super().showPage()
    
            super().save()
    
        def draw_page_number(self, page_count):
            """
            Add the page number
            """
            page = "Page %s of %s" % (self._pageNumber, page_count)
            self.setFont("Helvetica", 9)
            self.drawRightString(179 * mm, -280 * mm, page)
    

    To use it just change Canvas for NumberedCanvas when creating a new file. When the file is saved the numbers are added.