はじめに
今回の記事は、前回の記事の続きでもう少し汎用的に使えるようにしていきます。
先回のおさらい
Pythonが得意な方にお願いして、PythonでPDFを分割するpdfsplit.exeファイルを作成してもらい、PAD側でそれを呼び出して使うという方法を紹介しました。詳しくは、先回の記事をご覧いただけますと幸いです。
pdfsplit.exeの使い方
- pdffilesフォルダー直下のpdfsplit.exeと同じ階層に分割対象のPDFを保存する。
- PADでpdfsplit.exeを実行する。
- pdffilesフォルダーに分割されたPDFが連番付きで保存され、元のPDFファイルは削除される。
今回の記事でやりたい事
先回はPDF分割機能を1つだけPADに追加しましたが、今回はPAD側で3つのPDF関連の機能を追加して外部関数のように使う方法を紹介します。追加する機能は、以下の3つです。今回もPythonが得意な方に頼る前提となります。
- PDFのページ数取得
- PDFを単一ページのPDFへ連番付きで分割
- PDF全ページに透かし追加
Pythonが得意な人に頼む事
今回もPythonが得意な人に、複数の機能を持つpdffunctions.exeを作成して貰います。コードは以下を参考になさって下さい。
from pathlib import Path
from PyPDF2 import PdfReader,PdfWriter
import pyperclip
def main():
padinput = pyperclip.paste().split(',')
if padinput[0] == 'getpagenumbers':
pagenumber = getpagenumbers(padinput[1])
pyperclip.copy(pagenumber)
elif padinput[0] == 'pdfsplit':
splitpdf(padinput[1])
elif padinput[0] == 'addwatermark':
addwatermark(padinput[1],padinput[2],padinput[3])
def getpagenumbers(content_pdf: str):
reader = PdfReader(content_pdf)
return len(reader.pages)
def splitpdf(content_pdf: str):
reader = PdfReader(content_pdf)
for i in range(len(reader.pages)):
page=reader.pages[i]
writer=PdfWriter()
writer.add_page(page)
filename=str(Path(content_pdf).stem) + str(i+1) + '.pdf'
newfilepath=Path.cwd()/filename
with open(newfilepath,mode='wb') as f:
writer.write(f)
def addwatermark(
content_pdf: str,
stamp_pdf: str,
pdf_result: str,
):
reader = PdfReader(content_pdf)
writer = PdfWriter()
for index in range(len(reader.pages)):
content_page = reader.pages[index]
mediabox = content_page.mediabox
reader_stamp = PdfReader(stamp_pdf)
image_page = reader_stamp.pages[0]
image_page.merge_page(content_page)
image_page.mediabox = mediabox
writer.add_page(image_page)
with open(pdf_result, "wb") as fp:
writer.write(fp)
if __name__ == '__main__':
main()
Pythonのexe化は今回もcx_Freezeを使用しています。setup.pyも参考で載せておきます。
from cx_Freeze import setup, Executable
excludes = ['PyQt4','PyQt5','tkinter']
base = None
setup(
name='pdffunctions',
version='1.0',
description='PDF functions for PAD',
options={'build_exe':{'excludes':excludes}},
executables=[Executable('pdffunctions.py', base=base)]
)
コードの解説
簡単にpdffunctions.pyの内容を説明します。
各関数の説明
ここでは、4つの関数を作成しています。
- main():クリップボードの値(PADからの入力)をリスト形式で取得し、リストの最初の値に応じてgetpagenumbers(), splitpdf(), addwatermark()のいずれかの関数を実行。
- getpagenumbers():PDFのページ数を取得する関数。PDFのページ数は、クリップボードにコピーされる。
- splitpdf():PDFを単一ページののPDFへ連番付きで分割する関数。分割されたPDFは、分割対象と同じフォルダーに保存される。元のファイルはそのまま残す。
- addwatermark():PDF全ページに透かしを追加する関数。透かしのみを入れたPDFファイルを透かしを入れる対象PDFと同一フォルダーに保存。watermarkは、透かしという意味です。
※addwatermark()関数は、PyPDF2の公式ドキュメントに掲載されているwatermark()関数をほぼそのまま使用しています。
PADとの入出力
PADとPythonでデータの入出力は、クリップボードを介して行います。このため、PythonではPyperclipを使用しています。Pyperclipについては、以下を参照ください。
PADからカンマ区切りで①関数名, ②操作対象のPDFファイルの絶対パス, ③透かし画像のPDFファイルの絶対パス, ④透かしを入れた後のPDFの絶対パスをPythonに渡します。ここで、3番目と4番目の文字列はaddwatermark()関数の時のみ必要になります。
PADでPythonとの入出力で使用するアクションは、以下の2つです。
- クリップボードテキストを取得
- クリップボードテキストを設定
pdffunctions.exeの使い方
cx_Freezeでexe化が完了すると、exe.win-amd64-3.xのようなフォルダーが作成されます。この中に、画像のようなpdfsplit.exeファイルと関連ファイルが保存されています。このフォルダーをご使用のPCに保存します(配布して貰います)。今回は、フォルダー名をexe.win-amd64-3.x→pdffunctionsと変更しました。使い方と動作は非常にシンプルです。
- pdffunctionsフォルダー直下のpdffunctions.exeと同じ階層に、分割対象のPDFと透かしが保存されたwatermark.pdfを置く(addwatermark()関数を使用しないのであれば、watermark.pdfは必要ありません)。
- PADでpdfsplit.exeを実行する。この時、リスト形式で必要な情報を渡し、使用する関数を選択する。
- 選択した関数に応じて、以下のように動作する。
getpagenumber()関数: 対象PDFのページ数をクリップボードにコピーし、メッセージボックスにページ数を表示。
pdfsplit()関数: pdffunctionssフォルダーに分割されたPDFが連番付きで保存され、元のPDFファイルはそのまま残る。処理の完了を知らせるメッセージボックスを表示。
addwatermark()関数: 指定した絶対パスに透かしが追加されたPDFが保存される。処理の完了を知らせるメッセージボックスを表示。
PAD側の操作
準備
pdffunctionsフォルダーに操作対象のPDF(世界一やさしいPython RPA_抜粋.pdf)と透かしが入ったPDFファイル(watermark.pdf)を保存します。
世界一やさしいPython RPA_抜粋.pdfは、7ページあります。
watermark.pdfは、以下の通り透かしの画像を保存しています。
PADの全体フローと各フローの説明
PADの全体フローは、。エラー処理等は含んでいませんので16行とシンプルです。画像で示すように4つのブロックに分けて説明します。
①変数の設定
ここでは、1行目〜4行目で4つの変数を設定します。使う変数は、functionname、pdfpath、watermarkpath、resultpathです。それぞれの変数の説明は、以下の通りです。
1行目
functionname:関数名を格納
今回は、addwatermark()関数を選択するので、addwatermarkを値としています。PDFのページ数を取得したい場合は、getpagenumbers、PDFを分割したい場合はpdfsplitを値として設定します。
2行目
3行目
watermarkpath:透かし画像のPDFファイルの絶対パスを格納
4行目
resultpath:透かしを入れた後のPDFの絶対パスを格納
透かしを入れた後のPDFは、pdffunctionsフォルダー内にresult.pdfという名前で保存します。
②Pythonへの入力準備
PAD→Pythonへ情報をそのまま渡すためのアクションがありませんので、クリップボードテキストを設定のアクションを使用します。1行目〜4行目で設定した変数をカンマで区切ってクリップボードへコピーします。Pythonのプログラム内でカンマ区切りの入力をリスト形式に変換しています。
③Pythonの関数実行
Pythonの関数を「アプリケーションの実行」のアクションで実行します。「アプリケーションパス:」には、pdffunctions.exeの絶対パスを指定します。「作業フォルダー:」は、pdffunctionsフォルダーを指定します。10行目で「wait」アクションを使って、Pythonのプログラムが実行完了するまでの間の2秒待機させます。今回は、2秒にしていますがPDFのページ数が多い場合にはもう少し時間がかかるかもしれません。
④実行結果の表示
「Switch - Case」アクションで 変数functionnameの値によって、アクションを変えます。
9行目〜11行目:
pagenumbersが選択された場合のアクションです。Pythonのプログラムを実行すると、指定したPDFのページ数がクリップボードに保存されますので、10行目で「クリップボードテキストを取得」アクションで変数ClipboardTextにページ数を格納します。
「メッセージを表示」アクションで、取得したページ数をメッセージボックスで表示させるようにします。
12行目〜13行目:
pdfsplitが選択された場合のアクションです。Pythonのプログラムを実行すると、操作対応のPDFが同じフォルダー内に1ページ毎に連番付きで分割保存されます。13行目の「メッセージを表示」アクションで、PDF分割が完了したことを知らせるメッセージボックスを表示させます。
14行目〜15行目:
addwatermarkが選択された場合のアクションです。Pythonのプログラムを実行すると、操作対応のPDFにwatermark.pdfの透かしが追加され、result.pdfとして保存されます。15行目の「メッセージを表示」アクションで、透かしの追加処理が完了したことを知らせるメッセージボックスを表示させます。
PADの実行結果
それぞれの関数を実行した結果と全ての関数を実行した後のpdffunctionsフォルダーを示します。
pagenumbers関数を実行した結果
pdfsplit関数を実行した結果
addwatermark関数を実行した結果
以下のメッセージが表示されます。
result.pdfは、以下のように透かしが追加されます。
全ての関数を実行した後のpdffunctionsフォルダー
addwatermark()関数、getpagenumbers()関数、pdfsplit()関数の全てを実行した後は、pdffunctionsフォルダーは以下のようになります。
おわりに
今回はPDF関連の機能を1まとめにして、PADから外部関数のように使う方法を紹介させていただきました。
Pythonで実装できる機能は多岐に渡ります。たとえば、データの揺れを一括で修正するデータクレンジングの機能をython x Pandasで作成する等の使い方もあるかと思います。PADで見つからないアクションがあればPythonが得意な人に相談してみて下さい。そして、今回のようにPADに機能を追加して更に便利に使いこなしましょう。
この記事がどなたかのお役に立てれば幸いです。