min117の日記

初期desireもち。趣味Mac,メインFedora,仕事xp。

Python3 PDFにページ番号を付与する

f:id:min117:20201031134123p:plain

 

PDFにページ番号を付与したい。ユーザー向けにマニュアルや手引きを作っている人はけっこうコレに出くわすと思う。

f:id:min117:20201031131858p:plain

マニュアルは様々なファイル形式の合体で作られる。例えば本文はWord(.doc)や一太郎(.jtd)で、図はPowerPoint(.ppt)で、表はExcel(.xlsx)、ついにはVisioDocuworksの文書までが入り混じる。

 

これらのファイルを一つにまとめるにはいったんPDFにしてから合体するしかない。PDFの合体はshell(bash)のpdfuniteコマンドで一発でできる。

f:id:min117:20201031130548p:plain

www.atmarkit.co.jp

 

で、合体したPDF(今回は60ページ以上ある)にページ番号を付与したい。しかし、この方法がなかなか見つからない。ググってもまともな記事が出てこない。

 

唯一、Python3で実現している人がいた。

qiita.com

やってみる。

 

まずは reportlab のインストール。

$ pip3 install reportlab --user

f:id:min117:20201031131216p:plain

 

続いて pdfrw をインストールする。

$ pip3 install pdfrw --user

f:id:min117:20201031131339p:plain

※ 環境によっては --user は付けなくてもいいかも。我が家のLinuxでは必要だった(たぶん権限が原因)。

 

Python3で処理を書く。コードは上記の記事まんま真似してみる。ソースのファイル名は my_PDFPAGENUMBER.py にした。

 

$ vim my_PDFPAGENUMBER.py

f:id:min117:20201031131017p:plain

22行目…ページ番号だけ(総ページ数は不要)で出したい場合は f"{page_num}" にする。

25行目…ページ番号のフォントサイズは14にした。少し大きめにしたい。

 

仮に united.pdfというファイルにページ番号を付けたい場合、実行はこう。

 

$ python3 my_PDFPAGENUMBER.py united.pdf

f:id:min117:20201031133733p:plain


こんな感じでページ番号がつく。

f:id:min117:20201031131858p:plain

全てのページに一瞬で番号が付与される。

 

「いや、職場はWindowsだからPython入れられない」「職場にLinux環境ない」なんて場合もGoogle Cloud Platform(GCP)に接続して Cloud Shellを使えばOK。

 

職場のChromeからやるとこんな感じ。

f:id:min117:20201031132337p:plain

Googleアカウントさえあればできる。

GCPの環境構築に関しては別記事で書く。

 

今回のコードを書いて

f:id:min117:20201031132717p:plain

 

実行すればいい。

f:id:min117:20201031132553p:plain

ちなみにGCPにPDFをアップロード or ダウンロードしたい場合は、右上の「縦の…」からできる。

 


コピペ用

from reportlab.pdfgen.canvas import Canvas
from pdfrw import PdfReader
from pdfrw.toreportlab import makerl
from pdfrw.buildxobj import pagexobj
import sys
import os

if len(sys.argv) != 2 or ".pdf" not in sys.argv[1].lower():
    print(f"Usage: python {sys.argv[0]} <pdf filename>")
    sys.exit()
input_file = sys.argv[1]
output_file = os.path.splitext(sys.argv[1])[0] + "_pgn.pdf"

reader = PdfReader(input_file)
pages = [pagexobj(p) for p in reader.pages]

canvas = Canvas(output_file)

for page_num, page in enumerate(pages, start=1):
    canvas.doForm(makerl(canvas, page))

    footer_text = f"{page_num}/{len(pages)}"
    canvas.saveState()
    canvas.setStrokeColorRGB(0, 0, 0)
    canvas.setFont('Times-Roman', 14)
    canvas.drawString(290, 10, footer_text)
    canvas.restoreState()
    canvas.showPage()

canvas.save()