Word、Excel の書類に電子ハンコで押印する
決裁でハンコを押す作業を自動化し、 社内の書類業務のペーパーレス化を進めましょう。
DX (デジタルトランスフォーメーション)の波に乗って、これまで紙で決裁した書類を電子化するペーパーレス化が進められています。 しかし、形式的にでもハンコを押さないと落ち着かないという企業もあるのではないでしょうか。
今回のプログラムは、ExcelやWord のファイルから押印場所を探し、ハンコの画像を貼り付けるものです。
ハンコの偽造などを防ぐには、より本格的な「電子印鑑」 や 「電子署名」などを使う必要がありますが、今回はそれを簡単に真似してみました。
下のYouTube動画をご視聴後、記事を読み進めていただくと、わかりやすいです。
サンプルファイルは下のボタンからダウンロードすることができます。
プログラム実行の流れ
要はハンコの画像を、 押印欄に置いてくれるプログラムなんですね。 これもいろいろと応用が利きそうですね。
import os
import glob
import shutil
import openpyxl
import docx
from docx.shared import Cm
current_dir=os.getcwd()
stamp_image=openpyxl.drawing.image.Image(os.path.join(current_dir,"Izawa.png"))
my_folder="1.担当者"
my_list=my_folder.split(".")
os.chdir(os.path.join(current_dir,my_folder))
for file in glob.glob("*.xlsx"):
workbook=openpyxl.load_workbook(file)
sheet=workbook.active
row=0
column=0
for i in range(1,sheet.max_row+1):
for j in range(1,sheet.max_column+1):
if sheet.cell(row=i,column=j).value==my_list[1]:
row=i+1
column=j
break
column_letter=openpyxl.utils.get_column_letter(column)
stamp_image.height=sheet.row_dimensions[i].height*1.5
stamp_image.width=\
sheet.column_dimensions[column_letter].width*10
cell_address=column_letter+str(i)
sheet.add_image(stamp_image,cell_address)
workbook.save(file)
for file in glob.glob("*.docx"):
document=docx.Document(file)
for table in document.tables:
for i,row in enumerate(table.rows):
for j,cell in enumerate(row.cells):
if cell.text==my_list[1]:
i=i+1
paragraph=table.rows[i].cells[j].paragraphs[0]
run=paragraph.add_run()
run.add_picture(os.path.join(current_dir,"izawa.png"),width=Cm(1.35),height=Cm(1.35))
break
document.save(file)
os.chdir(current_dir)
my_folder=os.path.join(os.getcwd(),"1.担当者")
next_folder=os.path.join(os.getcwd(),"2.係長")
save_path=os.path.join(my_folder,"処理済")
os.makedirs(save_path,exist_ok=True)
os.chdir(my_folder)
for file in glob.glob("*.*"):
shutil.copy2(os.path.join(my_folder,file),next_folder)
shutil.copy2(os.path.join(my_folder,file),save_path)
os.remove(os.path.join(my_folder,file))
押印場所を探す仕組み
ハンコが必要な文書には、たいてい「社長」 「部長」 などの役職別の押印欄があります。 今回のプログラムは、対象の押印欄を探しそこにハンコを押すようになっています。
その仕組みは「1. 担当者」フォルダに文書が入っていたら「担当者」と入力されたセルの下にハンコを押し、 「5. 社長」 フォルダに文書が入っていたら 「社長」 と入力されたセルの下にハンコを押します。
実は「1.」 「5.」 といった数字は重要ではなく(ただし数字とピリオドは必要です)、フォルダ名後半の「担当者」 「社長」 「部長」 などの名前だけを見て、 それと一致するセルを探しているのです。
つまり、フォルダ名とセルに入力した役職名が合ってないとうまく働かないってことですね。
そうです。あと、今回のプログラムは 「1.担当者」 フォルダに固定しているので、社長や部長の欄にハンコを押すときは少しだけ変更が必要です
文書とハンコ画像の用意
今回のプログラムは、ExcelとWord の文書にハンコを押すことができます。
Excel ではセルのサイズに合わせてハンコサイズを調整できます。ただし、セルの縦横比に差があると画像も変形してしまうので、セル幅を調整してください。
また、Wordでは表を使って押印欄を作ってください。
ハンコの画像 (izawa.png) はイラストソフトやペイントソフトで作っています、プログラム (hanko.py) と同じフォルダに置いてください。
ハンコ画像の背景は透過設定にしておいてください。
プログラムの解説
hanko.pyを見てみましょう。 変数my_folder に文書を探すフォルダ名を指定しています。社長印や部長印を押したいときは、代入するものを「4. 部長」 「5.社長」 などに変更してください。
Excelファイルの処理
はじめに openpyxlパッケージのdrawing.image.Image (…) でExcelファイル用のハンコ画像を読み込みます。 Wordファイル用のハンコ画像はあとで別に読み込みます。
my_folder に自分の作業するフォルダ 「1. 担当者」 を指定し、 os.chdir関数で移動します。 このときsplitメソッドを使って、フォルダ名を「.」のところで分割しておきます。 分割後のmy_list はあとでハンコを押すセルを探すために使います。
globモジュールを使って「.xlsx」という拡張子が付いたファイルを繰り返し処理します。
globモジュールとは
globモジュールは、ファイルシステム内の指定されたパターンにマッチするすべてのファイルやディレクトリを取得するために使用されます。 このモジュールは、指定されたパターンにマッチするすべてのパス名を返す glob関数を提供します。
例えば、以下のように glob 関数を使用することで、特定のディレクトリ内にあるすべての .txtファイルを検索することができます。
Copy codeimport glob
txt_files = glob.glob('/path/to/dir/*.txt')
globモジュールを使用することで、簡単にファイルやディレクトリを検索することができます。
行と列の2重ループで 「担当者」 を含むセルを探す
1セルずつ順番に見ていって、見つかったらその場所を変数 row と変数 column に入れ、最後に変数 column の列番号を openpyxl.utils.get_column_letter 関数で文字に変換し、 変数 column_letterに代入しています。
openpyxl.utils.get_column_letter 関数は、OpenPyXL ライブラリの一部です。この関数は、Excel シートで使用される列の文字列表華 (A, B, C, …) を取得するために使用されます。
今回はハンコを挿入するセルを指定する際、 列は番号ではなく文字 (A、B、C…) で指定するためです。
ここから画像をセルに挿入する処理です。 ハンコ画像を押印欄のサイズに合わせて調整します。
まず押印欄のサイズを sheet.row/column_dimensions で調べ、それにある数を掛けた結果を stamp_image.height と stamp_image.width に設定します。
ハンコ画像の大きさは、ちょっとそれっぽさを出すために、押印欄から少しはみ出るように計算しています。
高さは1.5掛けて幅は10掛けていますが、これで正しいんですか?
Excelのセルのサイズは、高さはポイント、幅は標準フォントの文字数で表すんです。 そのため、計算方法が違うんですよ。
最後に add_image メソッドでハンコ画像を挿入し、 workbook.saveメソッドを使ってワークシートを上書き保存します。
Wordファイルの処理
Excelファイルのときと同じように、フォルダ内のWordファイルで繰り返し処理していきます。
tables 属性を使って、ドキュメントに含まれるすべての表に対して繰り返し処理を行います。
行と列の2重ループで「担当者」を含むセルを探し、見つかったらその1つ下の行に add_pictureメソッドでハンコ画像を挿入します。
Word側ではセルに画像サイズを合わせる調整は行っていません。 Cm 関数を使って1.35cmに設定しています。
プログラムの内容は微妙に違いますが、やっていることはExcelファイルのときとだいたい同じですね
そう、表の中からセルを探すという点では同じですから、プログラムの構造も似てくるんですね。
押印した書類を次の担当者のフォルダに移動する
押印するとともに、次の役職の人に渡す準備をするプログラムの部分を解説します。
たいていの書類の承認プロセスは、担当者から始まって上位の役職者へという順番で押印していくものです。 それを支援するために、自分の押印が終わったら、「処理済」フォルダと、次の役職に渡すためのフォルダにコピーするようにしてみます。
これなら処理済みのファイルがひと目でわかりますし、次の役職者がどのファイルを処理すればいいか見るのも簡単ですね。
パソコン内のフォルダにコピーして終わりなので、ファイルを手渡しする必要はあります。 ファイルサーバーと同期を取るような環境だったら、さらに実用的になります。
「1.担当者」 フォルダの中に 「処理済」 フォルダを作る必要がある点と、次の役職者のフォルダも必要な点には注意してください。 これらのフォルダがないと、ファイルのコピーに失敗してファイルが消えることもあります。
os.chdir(current_dir)
my_folder=os.path.join(os.getcwd(),"1.担当者")
next_folder=os.path.join(os.getcwd(),"2.係長")
save_path=os.path.join(my_folder,"処理済")
os.makedirs(save_path,exist_ok=True)
os.chdir(my_folder)
for file in glob.glob("*.*"):
shutil.copy2(os.path.join(my_folder,file),next_folder)
shutil.copy2(os.path.join(my_folder,file),save_path)
os.remove(os.path.join(my_folder,file))
まず「1.担当者」「2.係長」「処理済」フォルダのパスをそれぞれ変数に格納しています。
そしてchdir (my_folder) で自分の作業するフォルダに移動し、中にあるすべてのファイルで繰り返し処理を行っていきます。
つまり、ファイルを次の役職のフォルダと自分の処理済みのフォルダにコピーし、 自分のフォルダにある押印後のファイルを削除します。