22 Stimmen

Eine mehrzeilige (Absatz-)Fußzeile und Kopfzeile in reportlab

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?

33voto

jochen Punkte 3336

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)

14voto

NateB80 Punkte 181

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.

4voto

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.

2voto

shifloni Punkte 709

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)

1voto

Dfranc3373 Punkte 1851

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X