简体   繁体   中英

Can somebody give me generate PDF report with header(add a image),footer (page X of Y) and table of content with bookmark using reportlab?

I can generate a PDF with header and footer, and also can generate PDF with table of content, but I cannot generate pdf with header (a image),footer(x page of y) and table of content with bookmark together, I have spend several days to combine these three function together, but failed, who can give me some advice about it? what's wrong with my code, the pdf's table of content not shown, and say"Placeholder for table of contents 0"

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)])
        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))

if __name__ == "__main__":

    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)

Check your code indentation. The afterFlowable method should be defined inside of class MyDocTemplate :

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)])
        self.addPageTemplates(template)

    def afterFlowable(self, flowable):
        if isinstance(flowable, Paragraph):
            txt = flowable.getPlainText()
            style = flowable.style.name
            ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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