Python reportlab でPDF作成で、
”ページ番号 of 総ページ数"
を出力する場合、 reportlab の platypus 機能を
使わないで実現するのは、総ページ数算出の為に、Canvas の showPage() 実行をカウント
または、その予測計算をしなくてはならず、そういう処理ロジックをコーディングする
のはつらい。(書けないわけじゃないけど、酷くてあんまりだ。。。)
かと言って、platypus の Paragraph 配列に出力するものを突っ込んで、
reportlab で決められた SimpleDocTemplate のマージン等囲まれ、
決められた中でしか配置できないのも自由度が失われて嫌だ。
ページ番号 出力は、DocTemplate の build 引数で指定する
canvasmaker で ページ番号 を書きだすクラスを
指定するのだが、それだけを活かして、他のテンプレート
(既に存在するPDFをテンプレートにする方法)でPDFを作成する。
ページ番号作成クラス、開発ターゲットプロジェクト用に1つ用意しておく。
pagenumCanvas.py import して利用する
# -*- coding: UTF-8 -*- # pagenumCanvas.py : reportlab DocTemplate build canvasmaker=PageNumCanvas # from reportlab.pdfgen import canvas from reportlab.lib.units import mm class PageNumCanvas(canvas.Canvas): def __init__(self, *args, **kwargs): canvas.Canvas.__init__(self, *args, **kwargs) self.pages = [] def showPage(self): self.pages.append(dict(self.__dict__)) self._startPage() def save(self): page_count = len(self.pages) for page in self.pages: self.__dict__.update(page) self.draw_page_number(page_count) canvas.Canvas.showPage(self) canvas.Canvas.save(self) def draw_page_number(self, page_count): page = "Page %s of %s" % (self._pageNumber, page_count) self.setFont("Helvetica", 10) self.drawRightString(195 * mm, 272 * mm, page)
↑は。以下を参考にさせてもらった。ほとんどそのままだが。。。
http://www.blog.pythonlibrary.org/2013/08/12/reportlab-how-to-add-page-numbers/
http://code.activestate.com/recipes/546511-page-x-of-y-with-reportlab/
http://code.activestate.com/recipes/576832/
この pagenumCanvas.py と同じディレクトリで以下、サンプルを用意する。
# -*- coding: UTF-8 -*- from pdfrw import PdfReader from pdfrw.buildxobj import pagexobj from pdfrw.toreportlab import makerl from reportlab.pdfbase.cidfonts import UnicodeCIDFont from reportlab.pdfbase import pdfmetrics from reportlab.platypus import SimpleDocTemplate, Paragraph from reportlab.lib.styles import getSampleStyleSheet import reportlab.rl_config from pagenumCanvas import PageNumCanvas import webbrowser pdfmetrics.registerFont(UnicodeCIDFont('HeiseiKakuGo-W5')) center_w = reportlab.rl_config.defaultPageSize[0] / 2.0 center_h = reportlab.rl_config.defaultPageSize[1] / 2.0 # テンプレート読込 page = PdfReader('template.pdf', decompress=False).pages pp = pagexobj(page[0]) def laterPages(canvas, doc): # サンプルなので無理やりループする。(目的の印字処理) for i in range(4): if i > 0: canvas.showPage() canvas.doForm(makerl(canvas, pp)) canvas.saveState() canvas.setFont("HeiseiKakuGo-W5", 9) #----- 目的の出力 ----- canvas.drawCentredString(center_w, center_h, "あいう テスト") # canvas.restoreState() def run(): outfile = 'res.pdf' doc = SimpleDocTemplate(outfile) doc.build([Paragraph("", getSampleStyleSheet()['Normal'])] , onFirstPage=laterPages , onLaterPages=laterPages , canvasmaker=PageNumCanvas) # 結果をブラウザ表示 webbrowser.open(outfile) run()
↑ Paragraph の配列を SimpleDocTemplate の build に渡すのだが
、ここで敢えて空文字を1要素だけ渡す。
onFirstPage も、onLaterPages も同じメソッドを指定する!
canvasmaker で、pagenumCanvas.py の PageNumCanvas を指定する!
onFirstPage 、onLaterPages で指定するメソッド laterPages において、
・採用したいページテンプレートを適用させる。
・出力したいだけ任意に印字処理を実行する。
→ Canvasオブジェクトで draw Xxxx の処理を書ける。
・改ページも任意に実行することで、自動的に
PageNumCanvas がページカウント処理してくれる。
書いてみるとかなり強引だけど、reportlab の platypus を
じっくり読んでる暇が無い時は、これでも良いのでないだろうか。