Правильно добавляйте номера страниц и общее количество страниц в PDF с помощью ReportLab

Я пытаюсь создать документ с нумерацией страниц в формате «Страница x из y». Я попробовал подход NumberedCanvas (http://code.activestate.com/recipes/576832/, а также с форумов https://groups.google.com/forum/#!topic/reportlab-users/9RJWbrgrklI), но это противоречит моему интерактивному оглавлению (https://www.reportlab.com/snippets/13/).

Я понял из этого сообщения http://two.pairlist.net/pipermail/reportlab-users/2002-May/000020.html возможно использование форм, но примеры по этому поводу очень скудны и неинформативны. Кто-нибудь знает, как это можно реализовать с помощью форм (или исправить подход NumberedCanvas?)


person Yotam Alon    schedule 24.07.2018    source источник


Ответы (2)


Эта страница (http://www.blog.pythonlibrary.org/2013/08/12/reportlab-how-to-add-page-numbers/) объясняет хороший способ сделать это. Я внес некоторые изменения, чтобы лучше использовать наследование.

Он создает новый класс, который наследуется от класса ReportLab Canvas.

Это мой модифицированный код:

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)

Чтобы использовать его, просто измените Canvas на NumberedCanvas при создании нового файла. При сохранении файла добавляются числа.

person Martin    schedule 23.01.2020
comment
Великолепно! Не знал, что вы все еще можете рисовать на странице после того, как это будет сделано. - person Yotam Alon; 28.01.2020
comment
В принципе хорошая идея, но на сегодняшний день и при использовании python 3.6.x в результате я получаю пустой PDF с ошибками. - person SkyWalker; 29.04.2020
comment
@SkyWalker Я использую его в производстве в проекте с Python 3.6.8. Какую версию ReportLib вы используете? я в 3.5.34 - person Martin; 30.04.2020

Так что я закончил визуализировать документ дважды. Занимает пару секунд, но работает очень хорошо!

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)

Не на 100% доволен, но иногда берешь то, что можешь получить!

Убедитесь, что вы не передаете одни и те же объекты в первую и вторую сборку multiBuild, так как лаборатория отчетов добавляет к ним некоторые свойства во время первой сборки, что вызовет ошибки во второй сборке.

Я немного обеспокоен тем, что в какой-то момент объект холста может быть уничтожен или сброшен после сборки, поэтому, если кто-то из будущих людей захочет использовать это, будьте осторожны.

person Yotam Alon    schedule 30.07.2018