【问题标题】:A multiline(paragraph) footer and header in reportlabreportlab 中的多行(段落)页脚和页眉
【发布时间】:2012-02-08 07:35:50
【问题描述】:

在reportlab中拥有页脚和页眉的最佳方式是什么,而不仅仅是一条线,可以在onPage函数中使用canvas.drawString绘制。没有找到将类似段落的内容放入 onPage 函数的页眉/页脚的方法。处理此问题的最佳方法是什么?有没有办法将段落放入页脚?

【问题讨论】:

    标签: python pdf pdf-generation reportlab


    【解决方案1】:

    我会看看这个答案:

    Properly add page numbers and total number of pages to PDF using ReportLab

    有一个关于在 ReportLab 中使用 Story 和 SimpleDocTemplate 添加页眉和页脚的惊人示例

    【讨论】:

      【解决方案2】:

      在所有页面上添加页眉或页脚的其他方法:构建方法有参数可以做到这一点。

      不要在jochen的答案中使用框架和模板。在最后一行,使用

      doc.build(text, onFirstPage=footer, onLaterPages=footer)
      

      其余方法与 jochen 相同。

      【讨论】:

        【解决方案3】:

        我知道这有点旧,但我遇到了这个问题并且能够解决它。当您的 PDF 中有多个页面并希望在每一页上都有页脚/页眉时,您必须使用 NextPageTemplate('template_id')。我只是在编写相关代码,其余代码如上面的@jochen 示例所示。

        在我的例子中,我使用的是PageBreak(),我花了一段时间才明白为什么我只在首页获得页脚。

        from reportlab.platypus import Paragraph, PageBreak, PageTemplate, Frame, NextPageTemplate
        
        frame = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height, id='normal')
        template = PageTemplate(id='footer', onPage=footer, frames=[frame])
        
        
        # add a NextPageTemplate before a PageBreak to have the footer in the next page
        
        text.append(Paragraph('some text', style)),
        text.append(NextPageTemplate('footer')), # this will make the footer to be on the next page if exists
        text.append(PageBreak())
        doc.build(text)
        

        【讨论】:

          【解决方案4】:

          Jochen 的回答很棒,但我发现它不完整。它适用于页脚,但不适用于页眉,因为 Reportlab 将在页眉顶部绘制所有可流动的内容。您需要确保您创建的 Frame 的大小不包括标题占用的空间,因此 flowabls 不会打印在标题顶部。

          使用jochen的代码,这是一个完整的标题示例:

          from reportlab.lib.pagesizes import letter, cm
          from reportlab.lib.styles import getSampleStyleSheet
          from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate, Paragraph
          from functools import partial
          
          styles = getSampleStyleSheet()
          styleN = styles['Normal']
          styleH = styles['Heading1']
          
          def header(canvas, doc, content):
              canvas.saveState()
              w, h = content.wrap(doc.width, doc.topMargin)
              content.drawOn(canvas, doc.leftMargin, doc.height + doc.topMargin - h)
              canvas.restoreState()
          
          doc = BaseDocTemplate('test.pdf', pagesize=letter)
          frame = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height-2*cm, id='normal')
          header_content = Paragraph("This is a multi-line header.  It goes on every page.  " * 8, styleN)
          template = PageTemplate(id='test', frames=frame, onPage=partial(header, content=header_content))
          doc.addPageTemplates([template])
          
          text = []
          for i in range(111):
              text.append(Paragraph("This is line %d." % i, styleN))
          doc.build(text)
          

          注意框架的减重,它从框架的高度减去 2 厘米,以便为标题留出空间。 flowables 将打印在框架内,因此您可以更改框架的大小以允许不同大小的标题。

          我也发现我通常需要将变量传递到header中,所以我使用了一个分配给onPage的偏函数,以便可以传入header的内容。这样就可以根据内容有一个可变的header页面。

          【讨论】:

            【解决方案5】:

            您可以在 onPage 函数中使用任意绘图命令,因此您可以从您的函数中仅绘制一个段落(参见reportlab user guide 中的第 5.3 节)。

            这是一个完整的例子:

            from reportlab.lib.pagesizes import letter
            from reportlab.lib.styles import getSampleStyleSheet
            from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate, Paragraph
            
            styles = getSampleStyleSheet()
            styleN = styles['Normal']
            styleH = styles['Heading1']
            
            def footer(canvas, doc):
                canvas.saveState()
                P = Paragraph("This is a multi-line footer.  It goes on every page.  " * 5,
                              styleN)
                w, h = P.wrap(doc.width, doc.bottomMargin)
                P.drawOn(canvas, doc.leftMargin, h)
                canvas.restoreState()
            
            doc = BaseDocTemplate('test.pdf', pagesize=letter)
            frame = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height,
                           id='normal')
            template = PageTemplate(id='test', frames=frame, onPage=footer)
            doc.addPageTemplates([template])
            
            text = []
            for i in range(111):
                text.append(Paragraph("This is line %d." % i,
                                      styleN))
            doc.build(text)
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-08-14
              • 1970-01-01
              • 2021-08-29
              • 1970-01-01
              • 2021-01-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多