Python ReportLab - 带有 X of Y 页码的可点击目录

Posted

技术标签:

【中文标题】Python ReportLab - 带有 X of Y 页码的可点击目录【英文标题】:Python ReportLab - Clickable TOC with X of Y page numbering 【发布时间】:2013-04-09 02:45:33 【问题描述】:

使用 ReportLab 2.7、Python 2.7:

我可以在目录 (toc) 中创建一个带有可点击书签的 pdf,或者我可以创建一个带有“x of y”页码的 pdf,但是当我尝试同时执行这两个操作时,书签页(键)似乎中断了.

示例代码:

class MyDocTemplate(BaseDocTemplate):  
    def __init__(self, filename, **kw):
        self.allowSplitting = 0
        BaseDocTemplate.__init__(self, filename, **kw)
        template = PageTemplate('normal', [Frame(2.5*cm, 2.5*cm, 15*cm, 25*cm)]) #, id='F1'
        self.addPageTemplates(template)

def afterFlowable(self, flowable):
    if isinstance(flowable, Paragraph):
        txt = flowable.getPlainText()
        style = flowable.style.name
        if style == 'Heading1':
            key = 'h1-%s' % self.seq.nextf('heading1')
            self.canv.bookmarkPage(key)                
            self.notify('TOCEntry', (0, txt, self.page))
        elif style == 'Heading2':
            key = 'h2-%s' % self.seq.nextf('heading2')
            print key
            self.canv.bookmarkPage(key)
            self.notify('TOCEntry', (1, txt, self.page, key))

class NumberedCanvas(canvas.Canvas):
    def __init__(self, *args, **kwargs):
        canvas.Canvas.__init__(self, *args, **kwargs)
        self._saved_page_states = []

    def showPage(self):
        self._saved_page_states.append(dict(self.__dict__))
        self._startPage()

    def save(self):
        """add page info to each page (page x of y)"""
        num_pages = len(self._saved_page_states)
        for state in self._saved_page_states:
            self.__dict__.update(state)
            self.draw_page_number(num_pages)
            canvas.Canvas.showPage(self)
        canvas.Canvas.save(self)

    def draw_page_number(self, page_count):
        self.setFont('Times-Bold',14)
        self.drawRightString(7.6*inch,.5*inch,
        "Page %d of %d" % (self._pageNumber, page_count))

    h1 = PS(name = 'Heading1',
    fontSize = 14,
    leading = 16)
    h2 = PS(name = 'Heading2',
    fontSize = 12,
    leading = 14,
    leftIndent = 25)

    #Build story.
    story = []
    toc = TableOfContents()

    #For conciseness, using the same styles for headings and TOC entries
    toc.levelStyles = [h1, h2]
    story.append(toc)
    story.append(PageBreak())
    story.append(Paragraph('First heading', h1))
    story.append(Paragraph('Text in first heading', PS('body')))
    story.append(Paragraph('First sub heading', h2))
    story.append(Paragraph('Text in first sub heading', PS('body')))
    story.append(PageBreak())
    story.append(Paragraph('Second sub heading', h2))
    story.append(Paragraph('Text in second sub heading', PS('body')))
    story.append(Paragraph('Last heading', h1))
    doc = MyDocTemplate("mypdf.pdf")
    doc.multiBuild(story, canvasmaker=NumberedCanvas)

任何 cmets 将不胜感激。

【问题讨论】:

这个问题你解决了吗?我和你遇到同样的事情。 【参考方案1】:

发现这个最初寻找解决方案无济于事,但是,想出了一些对我有用的东西并希望分享如下:

reportlab 示例的起点是关于创建包含目录的文档(我假设您首先使用了该文档),请执行以下操作。

通过添加选项 onPage 和 onPageEnd 来修改 init 函数中的模板分配,这些选项定义了对用于在页面上绘制页眉和页脚的函数的调用,如下所示,猜测您可以只在一个函数中执行相同的操作,但是,我使用两个为了在我的用例中分隔页眉/页脚部分:

template = PageTemplate('normal', [Frame(2.5*cm, 2.5*cm, 15*cm, 25*cm, id='F1')],onPage=header,onPageEnd=footer)

将命名的页眉/页脚函数添加到您的类中,如下所示,并说明了一些用于澄清的选项,包括页脚函数中的页码,以确保问题得到回答:

def header(canvas, doc):
    canvas.saveState()
    canvas.drawImage('some_image.gif', 5,780, width=None,height=None,mask=None)
    canvas.setLineWidth(1)
    canvas.line(5,780,120,780)
    canvas.setFont('Times-Bold',16)
    canvas.drawString(108, 108, 'blah')
    canvas.restoreState()

def footer(canvas, doc):
    canvas.saveState()
    canvas.setFont('Times-Roman',9)
    canvas.drawImage('py.jpg', inch,inch, width=None,height=None,mask=None)
    canvas.drawString(inch, 0.75 * inch, "Page %d " % doc.page)
    canvas.restoreState()   

无论您对添加的“编号画布类”做了什么以及它为什么会中断,我不知道,但由于您提供的代码让我强烈地想起了 reportlab 目录示例,我想您可以从它开始,应用我建议的更改/添加,看看效果如何。

这应该可以解决问题,希望对您有所帮助!

【讨论】:

以上是关于Python ReportLab - 带有 X of Y 页码的可点击目录的主要内容,如果未能解决你的问题,请参考以下文章

带有 Reportlab 的 PyQt5 项目对 Pyinstaller 有问题

python 安装 reportlab 报错 “ImportError: No module named reportlab.lib”

Python Reportlab 生成PDF文档

在 python django 服务 ubuntu 中安装 reportLab

Python Reportlab 分页符

使用 Reportlab 的多个页面 - Django