前回、会社名や請求月といったキーワードで絞り込んで、Microsoft Excelにまとめられた請求先データや請求金額データを取り出す方法を説明した。今回は、これまでに作ったスクリプトをまとめ、会社名と請求月をキーにして請求書を自動生成する方法を説明する。Microsoft Excelで作成された請求書テンプレートなどから自動的に該当月請求書を作成する方法として参考になる方法だ

連載「PythonでExcel作業の効率化を図ろう」のこれまでの回はこちらを参照

請求先と請求金額データをはめ込む

今回は、次のような請求書テンプレートを用意した。「ソーシャル メディア、ドキュメント、デザイン用の無料テンプレート | Microsoft Create」から「税の計算を含むサービス請求書.xlsx」というファイルをダウンロードし、自社の情報を入力した状態のファイルだ。

  • 「税の計算を含むサービス請求書.xlsx」を多少編集したもの

    「税の計算を含むサービス請求書.xlsx」を多少編集したもの

このテンプレートファイルの請求先と請求金額に値をはめ込めば請求書になる。データを取り出す部分はこれまでの連載ですでに作ってあるので、それらをマージしてスクリプトを作る。

請求先と請求データを取り出すスクリプト

まずはこれまでに作成したスクリプトをマージして、請求先と請求データの双方を取り出すスクリプトを作成する。ここでは次のようなスクリプトを作成した。

gen_invoice_1.py

import argparse
import pandas

#=========================================================================
# 初期値を設定
#=========================================================================
billing_company_data_xlsx_file_path = '請求先データ.xlsx'
billing_data_xlsx_file_path = '請求データ.xlsx'
billing_company_name = 'マイナビシステムズD'
billing_month = '202401'

#=========================================================================
# コマンドライン引数を解析
#=========================================================================
parser = argparse.ArgumentParser(description='Excelデータファイルから指定された会社の指定された月の請求データを抽出します。')
parser.add_argument('-b', '--billingexcel', help='請求データExcelファイルのパス')
parser.add_argument('-c', '--companyexcel', help='会社データExcelファイルのパス')
parser.add_argument('-n', '--name', help='検索する会社名')
parser.add_argument('-m', '--month', help='対象月')
args = parser.parse_args()

if args.companyexcel:
    billing_company_data_xlsx_file_path = args.companyexcel
if args.billingexcel:
    billing_data_xlsx_file_path = args.billingexcel
if args.name:
    billing_company_name = args.name
if args.month:
    billing_month = args.month

#=========================================================================
# 指定された会社の会社データを取得
#=========================================================================
dataframe = pandas.read_excel(billing_company_data_xlsx_file_path)
company_data = dataframe[
    dataframe[dataframe.columns[0]] == billing_company_name
]

#=========================================================================
# 指定された会社の指定された月の請求データを取得
#=========================================================================
dataframe = pandas.read_excel(billing_data_xlsx_file_path, dtype={'対象月': str})
billing_data = dataframe[
    (dataframe[dataframe.columns[0]] == billing_company_name) &
    (dataframe[dataframe.columns[1]] == billing_month)
]

#=========================================================================
# 請求データを出力
#=========================================================================
i = company_data.index[0]

name = company_data.at[i,'会社名']
zip = company_data.at[i,'郵便番号']
address = company_data.at[i,'住所']
tel = company_data.at[i,'電話番号']
charge = company_data.at[i,'請求先名']
email = company_data.at[i,'メールアドレス']

print(f"{name} 【{billing_month}分請求内容】")
print(f"\t{zip} {address} - {tel}")
print(f"\t{charge} <{email}>")
print(f"")

for index, row in billing_data.iterrows():
    print(f"{index}: {row['項目名']} - {row['単価']} x {row['数']}"

おさらいも兼ねて、ポイントとなるコードを説明する。まず、次のコードで請求先の会社データが収納されたMicrosoft Excelファイルから該当会社の情報をデータフレームに取り出している。

指定された会社の会社データを取得

#=========================================================================
# 指定された会社の会社データを取得
#=========================================================================
dataframe = pandas.read_excel(billing_company_data_xlsx_file_path)
company_data = dataframe[
    dataframe[dataframe.columns[0]] == billing_company_name
]

pandas.read_excel()でExcelのデータをデータフレームとして取り出している。そこからさらに会社名が一致するデータのみを取得している。

同じ要領で次のコードで該当する企業の該当する月のデータをExcelから取り出している。

指定された会社の指定された月の請求データを取得

#=========================================================================
# 指定された会社の指定された月の請求データを取得
#=========================================================================
dataframe = pandas.read_excel(billing_data_xlsx_file_path, dtype={'対象月': str})
billing_data = dataframe[
    (dataframe[dataframe.columns[0]] == billing_company_name) &
    (dataframe[dataframe.columns[1]] == billing_month)
]

上記のコードは対象月の列のデータが整数として解釈されると困るので、pandas.read_excel()の引数に「dtype={'対象月': str}」を与えて明示的に文字列として読み出している。そして会社名と請求月で絞り込みを行って該当データのみのデータフレームを用意している。

取り出した会社情報に個別にアクセスする方法はいくつかあるが、ここでは次のようにデータフレームのat[]を使う方法を使用している。

データフレームのat[]でセルのデータにアクセス

i = company_data.index[0]

name = company_data.at[i,'会社名']
zip = company_data.at[i,'郵便番号']
address = company_data.at[i,'住所']
tel = company_data.at[i,'電話番号']
charge = company_data.at[i,'請求先名']
email = company_data.at[i,'メールアドレス']

gen_invoice_1.pyではこの取り出したデータを標準出力に表示するところまでを行っている。

  • gen_invoice_1.pyを編集中のようす

    gen_invoice_1.pyを編集中のようす

実行すると次のように指定した会社のデータと、その会社の指定した月の請求データが取得できていることがわかる。

  • gen_invoice_1.pyの実行結果

    gen_invoice_1.pyの実行結果

これでデータの取り出しは完了だ。