简体   繁体   English

使用 ReportLab 将页码和总页数正确添加到 PDF

[英]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".我正在尝试创建一个文档,该文档的页码格式为“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/ ).我已经尝试过 NumberedCanvas 方法( http://code.activestate.com/recipes/576832/以及论坛https://groups.google.com/forum/#!topic/reportlab-users/9RJWbrgrklI )但是与我的可点击目录 ( 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.我从这篇文章http://two.pairlist.net/pipermail/reportlab-users/2002-May/000020.html 中了解到,使用表单是可能的,但是这方面的例子非常稀少且没有信息量。 Does anybody have any idea on how this can be implemented using forms (or fixing the NumberedCanvas approach?)有没有人知道如何使用表单来实现这一点(或修复 NumberedCanvas 方法?)

This page ( http://www.blog.pythonlibrary.org/2013/08/12/reportlab-how-to-add-page-numbers/ ) explains a good way to do it.这个页面( http://www.blog.pythonlibrary.org/2013/08/12/reportlab-how-to-add-page-numbers/ )解释了一个很好的方法。 I made some changes to make better use of inheritance.我做了一些更改以更好地利用继承。

It creates a new Class that inherits from ReportLab Canvas class.它创建一个继承自 ReportLab Canvas 类的新类。

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.要使用它,只需在创建新文件时将Canvas更改为NumberedCanvas When the file is saved the numbers are added.当文件被保存时,数字被添加。

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!不是 100% 快乐,但有时你会得到你能得到的!

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.确保您没有将相同的对象传递给第一个和第二个 multiBuild,因为报告实验室在第一次构建期间向它们添加了一些属性,这将导致第二次构建中出现错误。

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.我有点担心画布对象可能会在构建后被销毁或重置,所以如果将来有人想要使用它,请小心。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM