申込書→契約書を自動変換するツールを作ってみた話
きっかけ
ある日、社内で契約を担当している人がぽつりと言っていた。「申込書を見ながら契約書に転記するのがしんどい。こういう仕組みがあったらいいんだけどね」と。
作れるな、と思ってすぐ作り始めた。
なぜ「Word→Word」なのか
正直に言うと、Wordで受け取った文書をWordに転記するという作業は、最初は想像もしていなかった。
データを扱う観点から言えば、ExcelやCSVのような構造化されたフォーマットで受け取るのが自然だと思っていた。入力フォームがあって、そこからデータが流れてくる——そういうイメージだ。
ところが契約の世界では、古くからの慣例で申込書がWordであることがいまだに存在する。そして厄介なのは、そこそこ大きな規模の組織になるほど、これが変えにくいということだ。
本部で様式が統一されていない、部署ごとに微妙に違うフォーマットが使われている、長年の慣習があるから現場が自発的に変えにくい——そういった実態がある。「フォームに統一すれば解決する」という正論は正しいが、その正論を通すためのコストが、現場では往々にして見合わないと判断される。
だから「今あるWordを読んで、今あるWordに書く」という課題が、2026年のいまも存在し続けている。
どんなツールか
申込書(Word)を読み取り、契約書テンプレート(Word)に自動転記するGUIアプリを作った。申込書のファイルかフォルダを選んで、契約締結日を入力して、ボタンを押すだけ。
1件でも、フォルダごと一括でも処理できる。Windowsの .exe で配布しているのでPythonの知識がなくても動く。
転記される項目はこのあたり。
| 申込書の項目 | 契約書の転記先 |
|---|---|
| 申込者 住所・会社名・役職氏名 | 乙 欄 |
| 契約締結日(GUI入力) | 1. 契約締結日 |
| プロジェクト名 | 2. 件名 |
| 目的及び内容 | 3. 目的・内容 |
| 期間 | 4. 期間 |
| 担当者(甲・乙) | 6. 担当者 |
| 直接経費・間接経費・総額 | 7. 経費 |
技術構成
- Word読み取り・書き込み:
python-docx - GUI:
tkinter(標準ライブラリなので追加インストール不要) - exe化:
PyInstaller --onefile
コアは extract.py(申込書からデータを抜く)と fill.py(契約書テンプレートに書き込む)の2ファイル。
ネストした表の読み取り
申込書はWordのテーブル構造で、大きなセルの中にさらに表が入っている構造だった。
nested_table = doc.tables[0].cell(0, 0).tables[0]
cell.tables でネスト表にアクセスできる。住所・会社名・役職氏名はこのネスト表の中にあり、正規表現で抽出した。
書式を壊さない書き込み
セルへの書き込みは cell.text = で直接書くと段落の書式が消えてしまう。既存のrunを再利用することで書式を保持した。
def _set_cell(cell, text: str):
for para in cell.paragraphs:
for run in para.runs:
run.text = ''
p = cell.paragraphs[0]
if p.runs:
p.runs[0].text = text
else:
p.add_run(text)
PyInstaller:テンプレートをバンドルする
.exe にWordテンプレートを同梱する必要があり、実行時は sys._MEIPASS から取り出す。
if getattr(sys, 'frozen', False):
_BUNDLE_DIR = Path(sys._MEIPASS)
_DEFAULT_TEMPLATE = _BUNDLE_DIR / "templates" / "契約書_template.docx"
配布物は .exe 1ファイルだけになった。
フィードバックの分析:「50%くらいかな」
試作版を渡してみたところ、「まだ50%くらいかな」という評価だった。
この50%という数字はリアルで正直なフィードバックだと思っている。詰めていくと、課題は大きく2つに整理できる。
① 申込書の情報だけでは契約書が完成しない 申込書に書かれていない情報が、契約書の表紙には必要になるケースがある。転記ツールがいくら精度を上げても、そもそもの入力データに含まれていない情報は補えない。ここは構造上の限界だ。
② 申込書フォーマットのゆれ 相手によって申込書の書き方が微妙に異なる。正規表現でパターンを吸収しているが、想定外の書き方をされると抽出が崩れる。実運用に耐えるには、フォーマットを固めるか、エラー検知を強化するかが必要になる。
このアプローチが活きる場所
上記の分析を踏まえると、すべてのケースに使えるツールではないというのが正直なところ。ただ、活きる場面は明確にある。
- 申込書のフォーマットが統一されていて、かつ契約書に必要な情報が申込書に揃っている相手
- 完成版ではなく、ドラフト生成として使う割り切り
後者は実用的だと思っている。何十件もの申込書を一括変換してドラフトを並べ、担当者が最終確認だけする、という流れであれば、50%の完成度でも十分に価値がある。「全部手で転記」と「完璧な自動化」の間にある選択肢として。
技術としての汎用性
「Word→Wordの定型転記」というパターン自体は、どの組織にも存在する。稟議書、報告書、各種申請書——入力フォームと出力テンプレートが決まっているものなら同じ構成で作れる。
python-docx + tkinter + PyInstallerの組み合わせは、相手PCにPythonが不要で、ダブルクリックで動くという点が現場への展開のしやすさに直結している。
今回の本当の収穫:社内ツール量産の型が固まった
個別ツールとしての完成度以上に、今回得た収穫がある。
exe形式で社内ツールを作るスタイルを標準化できたことだ。
- 処理ロジックを薄いモジュールに分ける(
extract.py/fill.py) - GUIは tkinter で統一(追加インストール不要)
PyInstaller --onefileで.exe1ファイルに固めるsys._MEIPASSでリソースをバンドルする定型パターン
一度この型を確立してしまえば、次のツールはロジックを差し替えるだけでいい。Word転記だけでなく、CSV処理、バーコード生成、ファイル変換——「ちょっと困っている作業」が出てきた場面に、短期間で .exe を渡せる体制が組める。
実際に同じ構成でバーコード付き帳票生成ツールも作っており、この雛形は機能している。
今回の案件で即採用には至らなかったが、量産できる仕組みができたことの方が長期的には大きいかもしれない。
まとめ
このツール単体での完成度は50%だったが、分析すれば何が足りないかは明確で、前提条件が整った場面では十分に使える。そして副産物として、社内ツールを素早く届けるための型が固まった。
作って、渡して、次に繋げる。それがこのスタイルの本質だと思っている。
こうした社内ツールの活用に関心のある方がいれば、まずは雑談ベースでも構いませんので、お気軽にご相談ください。