Python ReportLab - 可点击的TOC,带有Y页面编号

时间:2013-04-16 15:45:13

标签: python-2.7 pdf-generation reportlab

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

非常感谢任何评论。

1 个答案:

答案 0 :(得分:0)

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

以reportlab示例的起点开始,有关创建包含文档的toc(我假设您首先使用的是),请按以下步骤进行操作。

通过添加选项onPage和onPageEnd来定义init函数,以在页面上绘制页眉和页脚,从而修改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示例,我想您可以从此开始,应用我建议的更改/补充,看看进展如何。

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