0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Python】PDFに担当印・承認印(日付印)を自動で捺印するスクリプトを作った

0
Last updated at Posted at 2026-08-10

はじめに

会社業務ではペーパーレス化が進み、社内資料はもちろん社外に提出する資料もPDF形式で扱うのが一般的になってきました。一方で、従来は紙で行っていた押印だけが、そのままの運用でPDFに置き換わっているケースも少なくありません。

このケース、だいたい以下の2パターンで対応しているのではないでしょうか。

  1. 印刷してスタンプを押す → スキャナで再びPDF化する
  2. 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 というファイル名で保存してください。

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として保存する処理を行っています。

関数としては、mainadd_stamp_to_pdfdraw_stamp の順に呼び出されます。全体の処理フローは以下の通りです。

  1. サブフォルダ(outfiles)を作成
  2. PDFファイルを検索(見つからなければここで終了)
  3. 2で見つけたPDFをロードする
  4. スタンプを描画する
  5. 4で描画したPDFを、1のサブフォルダに保存
  6. 2に戻る(次のPDFを検索)

主な処理の解説

行番号 実行コード 解説
1-3 import fitz
from datetime import datetime
import 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研究所 で公開しています。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?