web-dev-qa-db-ja.com

reportlabの複数行(段落)のフッターとヘッダー

OnPage関数のcanvas.drawStringで描画できる、1行だけでなく、reportlabにフッターとヘッダーを含めるための最良の方法は何ですか。 onPage関数のヘッダー/フッターに段落のようなものを配置する方法が見つかりませんでした。これを処理するための最良の方法は何ですか?段落をフッターに入れる方法はありますか?

17
Aldarund

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)
28
jochen

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に割り当てられた部分関数を使用しました。このようにして、ページのコンテンツに基づいて変数ヘッダーを作成できます。 。

11
NateB80

すべてのページにヘッダーまたはフッターを追加するための追加のアプローチ:これを行うためのbuildメソッドには引数があります。

Jochenによる回答でフレームとテンプレートを使用しないでください。最後の行で、

doc.build(text, onFirstPage=footer, onLaterPages=footer)

残りのアプローチは、jochenからのものと同じになります。

2

私はこれが少し古いことを知っていますが、私はこの問題に遭遇し、それを解決することができました。 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)
1
shifloni