问题
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?)
回答1:
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.
回答2:
So I ended up rendering the document twice. Takes a couple more seconds, but works very well!
class MyDocTemplate(BaseDocTemplate):
def generate(self, story):
self.multiBuild(story[:])
# Decrease by one because canvas is at the page after the last
self.page_count = self.canv.getPageNumber() - 1
self.multiBuild(story[:])
class MyPageTemplate(PageTemplate):
def onPage(self, canvas, doc):
if getattr(doc, 'page_count', None) is not None:
canvas.drawString(x, y, canvas.getPageNumber(), doc.page_count)
Not 100% happy, but sometimes you take what you can get!
Make sure you do not pass the same objects to the first and second multiBuild, as report lab adds some properties to them during the first build, that will cause errors in the second build.
I am slightly concerned that at some point the canvas object might be destroyed or reset after the build, so if any future people want to use this, be careful.
来源:https://stackoverflow.com/questions/51498663/properly-add-page-numbers-and-total-number-of-pages-to-pdf-using-reportlab