Invoice Maker 第2回
はじめに:1枚できれば100枚できる
こんにちは、ニンジンです🥕
前回(第1回)では、Pythonで「1枚の請求書」をExcelから自動作成してPDF出力する基本ロジックを解説しました。ですが実務では、月末に数十枚〜数百枚の請求書を作ることになります。
この記事では、前回のコードを for ループ で拡張し、受注管理表に並んだ複数行のデータを次々と読み込んで一気に大量のPDFを生成します。あわせて、実務でツールを動かすなら必ず知っておきたい「ファイル名の重複回避」と「例外処理(try-finally)」も解説します。
この記事で分かること
for i in range()でExcelの行を1行ずつずらしながら読み込む書き方- f-string でファイル名を動的に作り、上書き(重複)を防ぐ方法
try...finallyで、エラー時もExcelのプロセスを確実に終了させる方法- 6件のサンプルデータから、6枚のPDFを一括生成するテストコード(全文)
「自分でコードを書く時間がない」「社内の誰でもクリックだけで使える完成品が欲しい」という方に向けて、本シリーズの最終形であるGUI搭載のフルパッケージ版 Invoice Maker (NINJIN EDITION) をnoteで頒布しています。
noteで見る →連続一括処理の事前準備
準備1:サンプルExcelファイル
お手持ちの管理表と書類フォーマットを使うか、下のサンプルを使ってください(第1回と同じファイルです)。
- 受注管理表_Sample.xlsx
- 請求書_Sample.xlsx
準備2:フォルダ構成とPython環境
同じフォルダの中に、次の3つを置きます。
- テストコード(この記事のコード)
- 受注管理表(Excel)
- 請求書の雛形(Excel)
複数データを一括処理するPythonスクリプト(全文)
連続処理に対応させたスクリプトの全体です。ファイルパスやシート名は自分の環境に合わせて変更してください。1行ずつコメントを付けてあります。
# invoice_maker_test02.py
# 受注管理表の複数行からデータを読み込み、請求書の雛形に書き込んでPDF化するサンプルコード
# invoice_maker_test01.pyをベースに、for文で複数行を処理するように拡張したコードです
import openpyxl
import win32com.client
import os
# 1. 設定
KANRI_PATH = "受注管理表_Sample.xlsx" # 変数KANRI_PATHに受注管理表のExcelファイルのパスを指定
HINAGATA_PATH = "請求書_Sample.xlsx" # 変数HINAGATA_PATHに請求書の雛形となるExcelファイルのパスを指定
# Excelアプリケーションの起動(ループの外で行うと高速です)
excel = win32com.client.Dispatch("Excel.Application") # DispatchでExcelアプリケーションを起動
excel.Visible = False # Excelのウィンドウを表示しない
excel.DisplayAlerts = False # 警告ダイアログを表示しない
excel.ScreenUpdating = False # 画面更新を停止(より徹底する場合)
try: # エラー発生時もExcelを確実に終了させるためにtryブロックを使用
wb_kanri = openpyxl.load_workbook(KANRI_PATH, data_only=True) # KANRI_PATHを開く data_only=Trueで数式の結果を値で取得
ws_kanri = wb_kanri["Sheet1"] # シート名を指定してシートを取得
# 2. for文で4行目から9行目まで繰り返す
# range(4, 10) は 4, 5, 6, 7, 8, 9 までを指します
for i in range(4, 10):
try: # for文の中でエラーが起きても次の行に進むように、ここでもtryブロックを使用
# 行番号(i)を使って各データを取得
order_id = ws_kanri[f"A{i}"].value # 受注番号 .valueでセルの値を取得
company_name = ws_kanri[f"C{i}"].value # 会社名
s_name = ws_kanri[f"F{i}"].value # 商品名
count = ws_kanri[f"G{i}"].value # 数量
amount = ws_kanri[f"H{i}"].value # 単価
print(f"--- 処理中({i}行目): {company_name} 様 ---")
# 3. 雛形へ書き込み
wb_hina = openpyxl.load_workbook(HINAGATA_PATH) #HINAGATA_PATHを開く
ws_hina = wb_hina["Sheet1"] # シート名を指定してシートを取得
ws_hina["A5"] = company_name #HINAGATA_PATHのA列5行目に会社名を書き込み
ws_hina["B18"] = s_name #HINAGATA_PATHのB列18行目に商品名を書き込み
ws_hina["L18"] = amount #HINAGATA_PATHのL列18行目に金額を書き込み
ws_hina["J18"] = count #HINAGATA_PATHのJ列18行目に数量を書き込み
# 一時ファイルのパス(会社名を含めて重複を避ける)
temp_excel = os.path.abspath(f"temp_{order_id}.xlsx") #abspathで絶対パスを取得 order_idを使って一時ファイルの名前を個別化する
wb_hina.save(temp_excel) # 保存してからPDF化する必要があるため、一時的なExcelファイルを作成
# 4. PDF化処理
output_pdf = os.path.abspath(f"請求書_{order_id}_{company_name}.pdf") # 出力するPDFのパスを作成(会社名と受注番号を含めて重複を避ける)
doc = excel.Workbooks.Open(temp_excel) # Openで先ほど保存した一時的なExcelファイル(temp.xlsx)を開く
doc.ExportAsFixedFormat(0, output_pdf) # ExportAsFixedFormatでPDF形式で保存。第1引数は0でPDF、第2引数は保存先のパス
doc.Close(False) # Closeでtemp.xlsxを閉じる。引数は変更を保存するかどうか(Falseで保存しない)
# 一時ファイルの削除
os.remove(temp_excel) # 一時的なExcelファイルを削除
print(f"成功: {output_pdf}")
except Exception as e: # エラーが発生しても次の行に進むための例外処理
print(f"【失敗】 {i}行目の処理でエラー: {e}")
finally:
# ループ内での後片付け(必要に応じて)
pass # 今回は特に後片付けはないですが、ここでExcelの設定をリセットすることもできます
finally:
# 5. Excelを完全に終了
excel.Quit()
print("すべての処理が完了しました。")実行結果:6件分のPDFが生成されれば成功
実務でトラブルを起こさないための3つの技
① for i in range() で行を1つずつずらす
for i in range(4, 10): と書くと、変数 i に 4・5・6・7・8・9 が順に入り、下のブロックが繰り返されます。ws_kanri[f"C{i}"] のように書けば、1周目は C4、2周目は C5 と、自動で行を下にずらしながらデータを取得できます。
② f-string でファイル名の重複(上書き)を防ぐ
前回はファイル名を "請求書_出力.pdf" で固定していました。これをループでやると、100回すべて同じ名前に上書きされ、最後の1社分しか残りません。
output_pdf = f"請求書_{order_id}_{company_name}.pdf"このように書くと「請求書_A001_株式会社〇〇.pdf」のように1件ずつ個別のファイル名になり、上書きされません。
③ try…finally でExcelのゴーストプロセスを防ぐ
PythonやVBAでExcelを裏側から操作するとき、いちばん厄介なのが「エラーで途中停止したのに、裏でExcelが起動したまま残る現象(ゴーストプロセス)」です。溜まるとPCが重くなります。
try:
# メインのループ処理
finally:
excel.Quit() # 絶対にExcelを終了させる!try:の中にメインの処理を書きます。finally:の中に「エラーが起きても起きなくても、必ず最後に実行する処理」を書きます。
この形にしておけば、途中で予期せぬエラーが出ても、裏側のExcelは確実に閉じられます。
まとめ:裏側の処理は完成、次は「操作画面」
このスクリプトを実行すると、指定した行のデータが順に読み込まれ、次々とPDFが生成されます。裏側の処理はこれで完成です。
ただし実務では、毎月処理する行数が変わります。「今月は4行目から50行目まで」となるたびに、コードの range(4, 51) を書き換えるのは、事務スタッフにとってハードルが高く、コードを壊すリスクもあります。
そこで次回・第3回では、CustomTkinterで「誰でもクリックと文字入力だけで使える操作画面(GUI)」を作り、ツールとして仕上げます。
シリーズの記事
「次回の解説まで待てない」「環境構築が面倒だから今すぐツールが欲しい」という方は、noteで完成版のGUIアプリ Invoice Maker (NINJIN EDITION) を頒布中です。ダウンロード後すぐに起動して使えます。
Invoice Maker (NINJIN EDITION) をnoteで確認する →よくある質問(FAQ)
Qrange(4, 10) はなぜ10まで書くのに9で止まるのですか?
APythonのrange(開始, 終了)は「終了の手前まで」という仕様です。range(4, 10)は4〜9の6個。Excelの4行目から9行目までを処理したいときは10と書きます。
QExcelのファイルがPDF化されず、エラーになります。
APDF変換部分(ExportAsFixedFormat)はMicrosoft ExcelがインストールされたWindowsでのみ動きます。Excelが入っていない環境やMacでは動きません。また、対象のExcelを開いたままだとロックされて失敗します。
Q処理の途中でエラーが出ても、残りの行は処理してほしいです。
Aこのコードはfor文の中にtry...exceptを入れてあるので、ある行でエラーが出ても【失敗】と表示して次の行に進みます。全体を止めたい場合はそのtryを外します。
Qdata_only=True は何のためにありますか?
A受注管理表に数式(合計金額など)が入っている場合、openpyxlは既定だと数式の文字列(=SUM(...))を返します。data_only=Trueを付けると、Excelが最後に計算した「結果の値」を読み込みます。
QExcelのゴーストプロセスが既に溜まっている場合はどうすればいいですか?
Aタスクマネージャーの「詳細」タブでバックグラウンドのEXCEL.EXEを探して終了するか、PCを再起動します。今回のtry...finallyを入れておけば、以降は溜まりません。
Qnoteで配布しているツールと、この記事のコードは何が違いますか?
Aこの記事のコードは「行番号を直接書き換える」前提の学習用です。配布版(Invoice Maker NINJIN EDITION)はGUIで行範囲やファイルを画面から指定でき、コードを触らずに使えます。
Follow me on X
本ブログの中の人「ニンジン🥕」はXやってます。新着記事はいち早くポストでお知らせしているので、見逃したくない方は @ninjin_py_vba をフォローしてみてください🥕
@ninjin_py_vba をフォローシリーズ記事一覧
電子工作・自動化ツールの製作記録をシリーズごとにまとめています。気になるテーマからお読みください。
-
FILE.01 — IoT
Raspberry Pi Pico W × GASラズパイPico W×GASで自作!「LINEで動く温湿度&スマートリモコン」完全ロードマップ
「外出中のペットの室温が心配…」そんな思いからスタートしたIoT自作プロジェクトの総集編。温湿度監視からエアコン遠隔操作まで、仕組みをゼロから作りたい方のための全5回の開発記録です。
シリーズを読む -
FILE.02 — CNC
Arduino × レーザー刻印CNCCNC自作シリーズ
高精度な加工を目指し、本格的な自作CNC製作に挑戦中。現在は基幹パーツであるオリエンタルモーターの納品を待つ「設計・準備編」を公開。ハードとソフトの両面から、理想のマシンを形にする過程をリアルタイムにお届けします。
シリーズを読む -
FILE.03 — XY軸制御
Raspberry Pi × ステッピングモーターXYテーブルシリーズ
Raspberry Piとステッパモーターを使い、ゼロから2軸制御に挑む記録。OS設定から回路設計、多軸制御のPythonコードまで、躓きやすいポイントを徹底図解。電子工作初心者が「動く感動」を味わうための実戦ガイドです。
シリーズを読む -
FILE.04 — 業務自動化
Python × Excel × CustomTkinter【Python開発記】NINJIN Mail制作記
PythonとExcelを連携させ、実務で即戦力となるメール送信ツールを開発。CustomTkinterによるUI構築や、ミスを防ぐテンプレート活用術など、現場の「痒い所に手が届く」自動化ノウハウを細部まで丁寧に解説します。
シリーズを読む -
FILE.05 — 業務自動化
Python × Excel × GUIアプリ化Invoice Maker(請求書・見積書自動作成)
手作業の請求書作成から卒業!PythonでExcelデータを読み込み一括PDF化する「Invoice_Maker」の作り方を全3回で解説。基本ロジックからGUIアプリ化まで、実務で役立つ自動化ノウハウが満載です。
シリーズを読む




コメント