Was ist der beste Weg, um eine Fußzeile und eine Kopfzeile in reportlab zu haben, die nicht nur eine einzelne Zeile ist, die mit canvas.drawString in der onPage Funktion gezeichnet werden kann. Ich habe keine Möglichkeit gefunden, in der onPage-Funktion so etwas wie einen Absatz in die Kopf-/Fußzeile einzufügen. Was ist der beste Weg, dies zu tun? Gibt es eine Möglichkeit, einen Absatz in die Fußzeile zu setzen?
Antworten
Zu viele Anzeigen?Sie können beliebige Zeichenbefehle in der onPage-Funktion verwenden, so dass Sie einfach einen Absatz zeichnen können (siehe Abschnitt 5.3 in der reportlab Benutzerhandbuch ) aus Ihrer Funktion.
Hier ist ein vollständiges Beispiel:
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)
Jochens Antwort ist großartig, aber ich fand sie unvollständig. Es funktioniert für Fußzeilen, aber nicht für Kopfzeilen, da Reportlab alle Flowables über der Kopfzeile zeichnen wird. Sie müssen sicherstellen, dass die Größe des Rahmens, den Sie erstellen, den von der Kopfzeile eingenommenen Platz ausschließt, damit die Flowables nicht über die Kopfzeile gedruckt werden.
Unter Verwendung des Codes von Jochen ist hier ein vollständiges Beispiel für Kopfzeilen:
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)
Achten Sie auf die Deklination des Rahmens, es werden 2 cm von der Höhe des Rahmens abgezogen, um Platz für die Kopfzeile zu schaffen. Die Flowables werden innerhalb des Rahmens gedruckt, so dass Sie die Größe des Rahmens ändern können, um verschiedene Größen von Kopfzeilen zu ermöglichen.
Außerdem muss ich in der Regel Variablen an die Kopfzeile übergeben, daher habe ich eine Teilfunktion verwendet, die onPage zugewiesen ist, damit der Inhalt der Kopfzeile übergeben werden kann. Auf diese Weise können Sie eine variable Kopfzeile basierend auf dem Inhalt der Seite haben.
Zusätzlicher Ansatz für das Hinzufügen der Kopf- oder Fußzeile auf allen Seiten: Es gibt Argumente für die Build-Methode, um dies zu tun.
Verwenden Sie nicht den Rahmen und die Vorlage in der Antwort von Jochen. Verwenden Sie in der letzten Zeile
doc.build(text, onFirstPage=footer, onLaterPages=footer)
Der Rest des Ansatzes ist der gleiche wie bei Jochen.
Ich weiß, dass dieser Artikel schon etwas älter ist, aber ich bin auf dieses Problem gestoßen und konnte es lösen. Wenn Sie mehr als eine Seite in Ihrer PDF-Datei haben und die Fußzeile/Kopfzeile auf jeder Seite haben möchten, müssen Sie NextPageTemplate('template_id')
. Ich schreibe nur den relevanten Code, da der Rest im obigen Beispiel von @jochen gezeigt wird.
In meinem Fall habe ich PageBreak()
und es dauerte eine Weile, bis ich verstand, warum ich nur die Fußzeile auf der ersten Seite angezeigt bekam.
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)
Ich würde mir diese Antwort ansehen:
Korrektes Hinzufügen von Seitenzahlen und Gesamtseitenzahl zu PDF mit ReportLab
Hat ein erstaunliches Beispiel für das Hinzufügen von Kopf- und Fußzeilen in ReportLab mit Story und SimpleDocTemplate