はじめに
会社業務ではペーパーレス化が進み、社内資料はもちろん社外に提出する資料もPDF形式で扱うのが一般的になってきました。一方で、従来は紙で行っていた押印だけが、そのままの運用でPDFに置き換わっているケースも少なくありません。
このケース、だいたい以下の2パターンで対応しているのではないでしょうか。
- 印刷してスタンプを押す → スキャナで再びPDF化する
-
Acrobat Readerのスタンプ機能を使って捺印する
手間を考えると1は論外として、2も地味に操作が面倒です。特に承認者の立場の人は複数の部下から承認依頼が来るので、なおさら手間になります。
そこで今回、PDFの「担当欄」または「承認欄」の下に日付印を自動で捺印するPythonスクリプトを作成しました。
日付印は(ビットマップではなく)描画機能で生成しているため、拡大してもきれいに表示されます。
出来上がりイメージはこんな感じです(サンプル画像)。
動作環境
以下の環境で動作確認しています。
| 項目 | バージョン等 |
|---|---|
| OS | Windows 11 |
| Python | 3.12 (win32, 64-bit) |
| PyMuPDF | 1.25.5 (MuPDF 1.25.6 ベース) |
できること
- スクリプトと同じフォルダに存在するPDFファイルから、文字列
"担 当"を見つけると、その下に日付印を捺印する - サブフォルダ
outfilesを作成し、捺印済みのPDFファイルを保存する - フォルダ内に複数のPDFファイルがある場合、上記の処理をファイル数分繰り返す
ソースコード
適当なフォルダに stamp_sample.py というファイル名で保存してください。
import fitz # PyMuPDF
from datetime import datetime
import os
SUBDIR = 'outfiles'
# "担 当" 又は "承 認"
ROLE = "担 当"
DIV_NAME = "第1営部" # 漢字パート
SIGN_NAME = " 佐藤 "
# ROLE = "承 認"
# DIV_NAME = " 部長" # 漢字パート
# SIGN_NAME = "鈴木太郎"
def draw_stamp(page, offset_x, offset_y, ratio):
shape = page.new_shape()
base_w = 100.0 * ratio
base_h = 100.0 * ratio
adjust = 3.0 * ratio
line_width = 1.5 * ratio
font_size1 = 23 * ratio
font_size2 = 16 * ratio
# 丸
center_x = base_w / 2.0 + offset_x
center_y = base_h / 2.0 + offset_y
radius = base_w / 2.0
shape.draw_circle((center_x, center_y), radius)
# 上線
y = base_h * 0.35 + offset_y
x1 = offset_x + adjust
x2 = offset_x + base_w - adjust
shape.draw_line ( ( x1, y), (x2, y) )
# 下線
y = base_h * 0.65 + offset_y
x1 = offset_x + adjust
x2 = offset_x + base_w - adjust
shape.draw_line ( ( x1, y), (x2, y) )
shape.finish(color=(1, 0, 0), width=line_width)
shape.commit()
# 部署追加
x1 = offset_x + adjust * 6
y1 = offset_y + adjust * 3
x2 = x1 + base_w
y2 = y1 + base_h
font_path = "C:\\Windows\\Fonts\\msmincho.ttc"
sign_rect = fitz.Rect(x1,y1,x2, y2)
page.insert_textbox(sign_rect, DIV_NAME, fontsize=font_size2, fontname="japan", fontfile=font_path, color=(1, 0, 0))
# サイン追加
x1 = offset_x + adjust * 6
y1 = offset_y + base_h * 0.70
x2 = x1 + base_w
y2 = y1 + base_h
sign_rect = fitz.Rect(x1,y1,x2, y2)
font_path = "C:\\Windows\\Fonts\\msmincho.ttc"
page.insert_textbox(sign_rect, SIGN_NAME, fontsize=font_size2, fontname="japan", fontfile=font_path, color=(1, 0, 0))
# 日付追加
x1 = offset_x + adjust
y1 = offset_y + base_h * 0.35
x2 = x1 + base_w
y2 = y1 + base_h
sign_rect = fitz.Rect(x1,y1,x2, y2)
date_txt = datetime.now().strftime("'%y.%m.%d")
font_path = "C:\\Windows\\Fonts\\msgothic.ttc"
page.insert_textbox(sign_rect, date_txt, fontsize=font_size1, fontfile=font_path, color=(1, 0, 0))
def add_stamp_to_pdf(input_pdf, output_pdf):
# PDFファイルを開く
pdf_document = fitz.open(input_pdf)
page = pdf_document[0]
text_instances = page.search_for(ROLE)
x0, y0, x1, y1 = text_instances[0]
x1 -= 22
y0 += 16
draw_stamp(page, x1, y0, 0.50)
# 出力PDFを保存
pdf_document.save(output_pdf)
# メイン
def main():
try:
os.mkdir(SUBDIR)
except:
print(SUBDIR,'フォルダは既に存在します')
files = os.listdir('.')
for input_file in files:
if '.pdf' in input_file:
output_file = SUBDIR + '\\' + input_file
add_stamp_to_pdf(input_file, output_file)
print(f"電子印を押したPDFファイルは {output_file} として保存されました。")
if __name__ == "__main__":
main()
注意事項
実行にあたっては、以下の点にご注意ください。
1. 失敗する可能性があるPDF
以下のようなPDFは処理に失敗する場合があります。
- パスワード付きPDF
- 編集禁止PDF
- 電子署名済みPDF
2. 書き込み権限のある場所で実行する
サブフォルダ(outfiles)とPDFファイルを新規作成するため、書き込み権限のない場所で実行すると失敗します。例えば以下のようなフォルダでの実行は避けたほうが良いです。
C:\Program Files- システム保護フォルダ
3. PyMuPDFのインストールが必要
pip install pymupdf
上記でエラーになる場合は、以下のように入力してください。
python -m pip install pymupdf
4. エラー処理は未実装
エラー処理はちゃんと実装されていません。例えば、PDF内にROLEで示された文字列が見つからなかった場合は例外になります。
実行方法
特にオプションは不要です。
python stamp_sample.py
例1: 担当印を捺印する場合
上記のソースコードのまま実行すると、"担 当" という文字列の下に担当印が捺印されたPDFファイルが outfiles フォルダに作成されます。
例2: 承認印(部長印)を捺印する場合
ソースコードの設定部分を以下のように変更すると、部長印が捺印されたPDFファイルが作成されます。
# "担 当" 又は "承 認"
# ROLE = "担 当"
# DIV_NAME = "第1営部" # 漢字パート
# SIGN_NAME = " 佐藤 "
ROLE = "承 認"
DIV_NAME = " 部長" # 漢字パート
SIGN_NAME = "鈴木太郎"
技術的解説
本スクリプトは、目印となる "担 当"(または "承 認")をサーチして、その近傍に日付印を描画し、新たにPDFとして保存する処理を行っています。
関数としては、main → add_stamp_to_pdf → draw_stamp の順に呼び出されます。全体の処理フローは以下の通りです。
- サブフォルダ(
outfiles)を作成 - PDFファイルを検索(見つからなければここで終了)
- 2で見つけたPDFをロードする
- スタンプを描画する
- 4で描画したPDFを、1のサブフォルダに保存
- 2に戻る(次のPDFを検索)
主な処理の解説
| 行番号 | 実行コード | 解説 |
|---|---|---|
| 1-3 |
import fitzfrom datetime import datetimeimport os
|
ライブラリロード fitz (PyMuPDF): PDFの読み込み・編集・保存 datetime: 日付・時刻処理(日付印用) os: フォルダ作成などのファイル操作 |
| 5 | SUBDIR = 'outfiles' |
変数:ファイル出力先(サブフォルダ) |
| 8-10 |
ROLE = "担 当"DIV_NAME = "第1営部"SIGN_NAME = " 佐藤 "
|
変数 ROLE: スタンプを捺印する場所の目印 DIV_NAME: スタンプの部署部分 SIGN_NAME: スタンプの名前部分 |
| 16-72 | def draw_stamp(page, offset_x, offset_y, ratio): |
スタンプの描画処理 page: (引数)PDFのページオブジェクト offset_x/offset_y: スタンプを描く座標 ratio: スタンプの大きさ |
| 74-90 | def add_stamp_to_pdf(input_pdf, output_pdf): |
PDFの読み込みと書き込み input_pdf: 入力ファイル(読み込むPDF)のファイル名 output_pdf: 出力ファイル(書き込むPDF)のファイル名 |
| 93-105 | def main(): |
メインルーチン ①サブフォルダ( outfiles)を作成②カレントフォルダで .pdf ファイルを検索 → 見つければ出力ファイル名を作成③入力/出力PDFファイル名を引数に add_stamp_to_pdf を呼び出し |
まとめ
今回紹介したスクリプトは、PDFの書式に強く依存するため、自分の環境で使う場合は調整が必須です。
しかし必要な要素技術は一通り詰め込んであるので、マルチページ対応など工夫次第でいろいろな書式に応用できます。毎日同じ書式のPDFに捺印している方には便利だと思うので、ぜひ活用してみてください。
参考
改訂記録
2026/08/10 初版公開
その他の記事は BB研究所 で公開しています。
