2012-01-11 20 views
15

¿Cuál es la mejor manera de tener un pie de página y un encabezado en el informe, que no solo una línea, que se puede dibujar con canvas.drawString en la función onPage. No encontré la manera de poner algo como Párrafo en el encabezado/pie de página en la función onPage. ¿Cuál es la mejor manera de manejar esto? ¿Hay alguna manera de poner un párrafo en el pie de página?Un pie de página y encabezado de varias líneas en el informe

Respuesta

23

Puede utilizar comandos de dibujo arbitrarios en la función onPage, por lo que puede dibujar un párrafo (consulte la sección 5.3 en el reportlab user guide) desde su función.

Aquí es un ejemplo completo:

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

respuesta de Jochen es grande, pero me pareció incompleta. Funciona para los pies de página, pero no para los encabezados, ya que Reportlab dibujará todos los flowables en la parte superior del encabezado. Debe asegurarse de que el tamaño del Marco que crea excluye el espacio ocupado por el encabezado, por lo que los flowabls no se imprimen en la parte superior del encabezado.

Mediante el código de Jochen, aquí es un ejemplo completo para los encabezados:

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) 

Tenga en cuenta el decleration del marco, se resta 2 cm de la altura del marco para permitir espacio para la cabecera. Los flowables se imprimirán dentro del marco para que pueda cambiar el tamaño del marco para permitir varios tamaños de encabezados.

También encuentro que generalmente necesito pasar variables al encabezado, así que utilicé una función parcial asignada a onPage para que se pueda pasar el contenido del encabezado. De esta manera puede tener un encabezado variable basado en el contenido de la página.

0

Sé que esto es un poco viejo, pero me he encontrado con este problema y pude resolverlo. Cuando tiene más de una página en su PDF y desea tener el pie de página/encabezado en cada página, debe usar NextPageTemplate('template_id'). Solo estoy escribiendo el código relevante ya que el resto se muestra en el ejemplo de @jochen anterior.

En mi caso, estaba usando PageBreak() y me tomó un tiempo entender por qué solo estaba obteniendo el pie de página en la primera página.

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) 
Cuestiones relacionadas