reportlab中的多行(段落)页脚和标题

时间:2012-01-11 22:48:33

标签: python pdf pdf-generation reportlab

在reportlab中有一个页脚和页眉的最佳方法是什么,这不仅仅是一行,可以在onPage函数中使用canvas.drawString绘制。没有找到一种方法将类似Paragraph的东西放入onPage函数的页眉/页脚中。处理这个问题的最佳方法是什么?有没有办法将段落放入页脚?

5 个答案:

答案 0 :(得分:26)

您可以在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)

答案 1 :(得分:9)

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将在框架内打印,因此您可以更改框架的大小以允许各种尺寸的标题。

我还发现我通常需要将变量传递到头文件中,因此我使用了分配给onPage的部分函数,​​以便可以传入头文件的内容。这样你就可以根据内容获得一个变量头页面。

答案 2 :(得分:1)

我知道这有点旧,但我遇到了这个问题,并且能够解决它。当您的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)

答案 3 :(得分:1)

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

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

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

其余方法与jochen的方法相同。

答案 4 :(得分:0)

我会看看这个答案:

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

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