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

问题描述 投票:0回答:2

使用 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)

如有任何意见,我们将不胜感激。

python-2.7 pdf-generation reportlab
2个回答
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 toc示例,我想您可以从它开始,应用我建议的更改/添加并看看进展如何。

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


0
投票

问题出在 NumberedCanvas 类中重写的 showPage 方法上,您必须调用父 showPage 方法:

class NumberedCanvas(canvas.Canvas):

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

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

    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))
© www.soinside.com 2019 - 2024. All rights reserved.