Nicolás, parte de este gran equipo de trabajo, nos ha hecho el favor de crear esta sección porque domina a la perfección este tema.
Solución:
Puede usar comandos de dibujo arbitrarios en la función onPage, por lo que solo puede dibujar un párrafo (consulte la sección 5.3 en la guía del usuario de reportlab) desde su función.
Aquí hay 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)
La respuesta de Jochen es genial, pero la encontré incompleta. Funciona para pies de página, pero no para encabezados, ya que Reportlab dibujará todos los elementos fluidos en la parte superior del encabezado. Debe asegurarse de que el tamaño del marco que cree excluya el espacio que ocupa el encabezado para que no se impriman flowabls en la parte superior del encabezado.
Usando el código de jochen, aquí hay un ejemplo completo para 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)
Ojo con la decleración del Frame, le resta 2 cm a la altura del frame para dejar espacio a la cabecera. Los fluidos 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 el contenido del encabezado pueda pasarse. De esta manera, puede tener un encabezado variable basado en el contenido de la página. .
Enfoque adicional para agregar el encabezado o pie de página en todas las páginas: hay argumentos para que el método de compilación haga esto.
No use el marco y la plantilla en la respuesta de jochen. En la última línea, utilice
doc.build(text, onFirstPage=footer, onLaterPages=footer)
el resto del enfoque será el mismo que el de jochen.
Sección de Reseñas y Valoraciones
Acuérdate de que puedes optar por la opción de parafrasear tu experiencia .