在reportlab中添加多行(段落)页脚和页眉

21 投票
5 回答
25658 浏览
提问于 2025-04-17 10:03

在使用ReportLab这个库的时候,怎么才能在报告的页眉和页脚中放入不仅仅是一行文字的内容呢?我想用canvas.drawString这个方法在onPage函数里绘制它们。但是我找不到办法把像段落这样的内容放进页眉或页脚里。有没有什么好的方法来处理这个问题?有没有办法把段落放到页脚里呢?

5 个回答

4

另一种在所有页面上添加页眉或页脚的方法:可以在构建方法中使用一些参数来实现。

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

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

其余的方法和jochen的做法是一样的。

14

Jochen的回答很好,但我觉得不够完整。它适用于页脚,但不适用于页眉,因为Reportlab会把所有的内容绘制在页眉的上面。你需要确保你创建的框架(Frame)的大小不包括页眉占用的空间,这样内容就不会打印在页眉上面。

使用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厘米,以留出空间给页眉。内容会在框架内打印,所以你可以调整框架的大小,以适应不同大小的页眉。

我还发现我通常需要把变量传递到页眉中,所以我使用了一个部分函数并将其分配给onPage,这样就可以把页眉的内容传递进去。这样,你就可以根据页面的内容来设置可变的页眉。

33

在onPage这个函数里,你可以使用任何绘图命令,所以你可以直接从你的函数里画出一段文字(具体可以参考reportlab用户指南的第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)

撰写回答