2012-01-11 564 views
15

什么是在reportlab中有一个页脚和页眉的最佳方式,不仅仅是一行,可以在onPage函数中使用canvas.drawString进行绘制。没有找到一种方法来将段落等内容放入onPage函数的页眉/页脚中。处理这个问题的最好方法是什么?有没有办法将一个段落放入页脚?reportlab中的多行(段落)页脚和页眉

回答

23

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

约亨的答案是伟大的,但我发现它不完整的。它适用于页脚,但不适用于页眉,因为Reportlab将在页眉顶部绘制所有流动页面。您需要确保您创建的框架的大小不包括标题占用的空间,因此流程标签不会打印在标题顶部。

使用约亨的代码,这里是头一个完整的例子:

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) 

注重框架的decleration,它减去从帧的高2厘米留出空间的标题。流动件将打印在框架内,因此您可以更改框架的尺寸以适应各种尺寸的页眉。

我还发现我通常需要将变量传递到头文件中,所以我使用了分配给onPage的部分函数,​​以便可以传入头文件的内容。这样您就可以拥有一个基于页面的内容。

0

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