OnPage関数のcanvas.drawStringで描画できる、1行だけでなく、reportlabにフッターとヘッダーを含めるための最良の方法は何ですか。 onPage関数のヘッダー/フッターに段落のようなものを配置する方法が見つかりませんでした。これを処理するための最良の方法は何ですか?段落をフッターに入れる方法はありますか?
OnPage関数では任意の描画コマンドを使用できるため、関数から段落を描画するだけです( reportlabユーザーガイド のセクション5.3を参照)。
完全な例を次に示します。
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)
Jochenの答えは素晴らしいですが、私はそれが不完全であることに気づきました。 Reportlabはすべてのフローアブルをヘッダーの上に描画するため、フッターでは機能しますが、ヘッダーでは機能しません。作成するフレームのサイズに、ヘッダーが占めるスペースが含まれていないことを確認して、flowablsがヘッダーの上に印刷されないようにする必要があります。
Jochenのコードを使用して、ヘッダーの完全な例を次に示します。
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)
フレームのデクレレーションに注意してください。フレームの高さから2cmを差し引いて、ヘッダー用のスペースを確保します。フローアブルはフレーム内に印刷されるため、フレームのサイズを変更して、さまざまなサイズのヘッダーに対応できます。
また、通常は変数をヘッダーに渡す必要があることもわかったので、ヘッダーのコンテンツを渡すことができるように、onPageに割り当てられた部分関数を使用しました。このようにして、ページのコンテンツに基づいて変数ヘッダーを作成できます。 。
すべてのページにヘッダーまたはフッターを追加するための追加のアプローチ:これを行うためのbuildメソッドには引数があります。
Jochenによる回答でフレームとテンプレートを使用しないでください。最後の行で、
doc.build(text, onFirstPage=footer, onLaterPages=footer)
残りのアプローチは、jochenからのものと同じになります。
私はこれが少し古いことを知っていますが、私はこの問題に遭遇し、それを解決することができました。 PDF)に複数のページがあり、すべてのページにフッター/ヘッダーを配置する場合は、NextPageTemplate('template_id')
を使用する必要があります。関連するコードのみを記述しています。残りは上記の@jochenの例に示されています。
私の場合、PageBreak()
を使用していましたが、最初のページにフッターしか表示されない理由を理解するのに少し時間がかかりました。
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)