2012-01-11 12 views
15

Qual è il modo migliore per avere un piè di pagina e un'intestazione in reportlab, non solo una singola riga, che può essere disegnata con canvas.drawString nella funzione onPage. Non ho trovato un modo per inserire qualcosa come Paragrafo nell'intestazione/piè di pagina nella funzione di pagina. Qual è il modo migliore per gestire questo? C'è un modo per inserire un paragrafo nel footer?Un piè di pagina (paragrafo) multilinea e un'intestazione in reportlab

risposta

23

È possibile utilizzare i comandi di disegno arbitrario nella funzione di pagina, in modo che sia possibile disegnare un paragrafo (vedere la sezione 5.3 in reportlab user guide) dalla propria funzione.

Ecco un esempio 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

risposta di Jochen è grande, ma mi è sembrato incompleto. Funziona per i piè di pagina, ma non per le intestazioni in quanto Reportlab disegna tutti i fluidi in cima all'intestazione. Devi essere sicuro che la dimensione del Frame che hai creato escluda lo spazio occupato dall'intestazione in modo che i flowabl non vengano stampati sopra l'intestazione.

Usando il codice di jochen, ecco un esempio completo per le intestazioni:

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) 

Attenzione alla decleration del frame, sottrae 2 cm dalla altezza del telaio per permettere spazio per l'intestazione. I flowable verranno stampati all'interno del frame in modo da poter modificare le dimensioni del frame per consentire varie dimensioni di intestazioni.

Inoltre, di solito ho bisogno di passare le variabili nell'intestazione, quindi ho usato una funzione parziale assegnata a onPage in modo che il contenuto dell'intestazione possa essere passato. In questo modo è possibile avere un'intestazione variabile basata sul contenuto della pagina.

0

So che questo è un po 'vecchio ma ho riscontrato questo problema ed è stato in grado di risolverlo. Quando hai più di una pagina nel tuo PDF e vuoi avere il piè di pagina/intestazione su ogni pagina, devi usare NextPageTemplate('template_id'). Sto solo scrivendo il codice rilevante mentre il resto è mostrato nell'esempio @jochen sopra.

Nel mio caso, stavo usando PageBreak() e mi ci è voluto un po 'per capire perché stavo solo ottenendo il piè di pagina nella prima pagina.

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) 
Problemi correlati