Python | 自動化:Excel レポート自動作成

Python
スポンサーリンク

概要(「決まった Excel レポート」を毎回ボタン一発にする)

Excel レポート自動作成は、
「毎月・毎週・毎日、ほぼ同じレイアウトの Excel を作る仕事」を
Python に肩代わりさせることです。

やることの流れは、だいたい次のようなイメージになります。

データ(CSV・DB・別の Excel)を読み込む。
pandas で集計や加工を行う。
テンプレートの Excel に書き込む、もしくは新規に書き出す。
必要なら書式(数値フォーマット・色・罫線・グラフ)も自動で設定する。

ここでは、初心者でも手を動かしやすいように、
「シンプルな日次売上レポート」を例にしながら、テンプレ型と新規作成型の両方をかみ砕いて説明します。


基本準備(フォルダ構成とライブラリ選定)

最低限そろえておきたいライブラリ

Excel レポート自動作成では、主役は pandas です。
書き出しのエンジンとして openpyxl や xlsxwriter を使います。

ターミナルやコマンドプロンプトで次のように入れておきます。

pip install pandas openpyxl xlsxwriter

pandas から to_excel を呼ぶとき、engine を指定すると xlsxwriter の書式機能を使いやすくなります。

フォルダ構成の例と Path の使い方

自動化を前提にするなら、フォルダ構成を先に決めておくと安定します。

たとえば次のような構成を想定します。

project_root
 ┗ data/ (元データの CSV など)
 ┗ output/ (作成されたレポート Excel)
 ┗ template/ (Excel テンプレート)
 ┗ scripts/ (Python スクリプト)

Python では、スクリプトの場所を基準に絶対パスを組み立てる癖をつけると、
どこから実行しても壊れなくなります。

from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent   # scripts の一つ上を基準にする
DATA_DIR = BASE_DIR / "data"
OUT_DIR = BASE_DIR / "output"
TEMPLATE_DIR = BASE_DIR / "template"

OUT_DIR.mkdir(exist_ok=True)
Python

この「BASE_DIR を起点に Path で組み立てる」パターンは、Excel 自動化を含むバッチ系で非常に重要です。


例題データの準備と集計(pandas でレポートの中身を作る)

想定する元データ(売上明細の CSV)

次のような CSV が毎日増えていく場面を想定します。

列は、日付、店舗名、カテゴリ、売上金額。
ファイル名は、sales_2025-01-01.csv のように日付入り。

まずはこの CSV を読み込んで、「店舗別・カテゴリ別の集計表」を作ります。

import pandas as pd
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent
DATA_DIR = BASE_DIR / "data"

csv_path = DATA_DIR / "sales_2025-01-01.csv"

df = pd.read_csv(csv_path, encoding="utf-8")

df["date"] = pd.to_datetime(df["date"], errors="coerce")
df["amount"] = pd.to_numeric(df["amount"], errors="coerce")
Python

ここで date と amount をきちんと型変換するのが重要です。
数値や日付が文字列のままだと、集計やソートがうまく動きません。

店舗別・カテゴリ別の売上集計

レポートの中に、「店舗×カテゴリの売上一覧」を Excel で出したいとします。
pandas の groupby と pivot_table を使うと一発で作れます。

summary = (
    df.groupby(["store", "category"], as_index=False)["amount"]
      .sum()
      .rename(columns={"amount": "total_amount"})
)

pivot = summary.pivot_table(
    index="store",
    columns="category",
    values="total_amount",
    aggfunc="sum",
    fill_value=0
)

print(pivot)
Python

この pivot が、そのまま Excel の「ピボットテーブルっぽい表」として使える形になります。


パターン1:新規に Excel レポートを作る(pandas + xlsxwriter)

to_excel でシンプルなレポートファイルを出力する

まずはテンプレートを使わずに、新しく Excel ファイルを作ってみます。

from datetime import datetime

OUT_DIR = BASE_DIR / "output"
OUT_DIR.mkdir(exist_ok=True)

report_date = df["date"].dt.date.max()
out_path = OUT_DIR / f"sales_report_{report_date}.xlsx"

with pd.ExcelWriter(out_path, engine="xlsxwriter") as writer:
    df.to_excel(writer, sheet_name="明細", index=False)
    pivot.to_excel(writer, sheet_name="集計")
Python

この段階で、「明細」シートと「集計」シートを持つ Excel ができあがります。
見た目は素っ気ないですが、ここまで来れば「機械で計算した正しい数字のレポート」が、毎回同じ手順で出せるようになります。

xlsxwriter で書式・見た目を整える

もう少し Excel らしく整えてみます。
xlsxwriter のフォーマットオブジェクトを使うと、
ヘッダーを太字にしたり、金額をカンマ付き表示にしたりできます。

with pd.ExcelWriter(out_path, engine="xlsxwriter") as writer:
    df.to_excel(writer, sheet_name="明細", index=False)
    pivot.to_excel(writer, sheet_name="集計")

    workbook  = writer.book
    sheet_sum = writer.sheets["集計"]

    header_format = workbook.add_format({
        "bold": True,
        "bg_color": "#D9E1F2",
        "border": 1,
        "align": "center"
    })

    money_format = workbook.add_format({
        "num_format": "#,##0",
        "border": 1
    })

    for col_num, value in enumerate(pivot.reset_index().columns.values):
        sheet_sum.write(0, col_num, value, header_format)

    nrows, ncols = pivot.reset_index().shape
    for row in range(1, nrows + 1):
        for col in range(1, ncols):    # 0列目は店舗名なので金額ではない
            sheet_sum.write(row, col, pivot.values[row - 1, col - 1], money_format)

    sheet_sum.set_column(0, 0, 15)
    sheet_sum.set_column(1, ncols, 12)
Python

大事なポイントは、pandas で書き込んだあとに、writer.book と writer.sheets を使って
セルのフォーマットを上書きしているところです。

最初は「素の to_excel で出力してから」「必要なところだけ整える」という流れで十分です。
慣れてきたら、「列幅を自動で調整する」「条件付き書式を使う」「グラフを追加する」などを足していけます。


パターン2:既存の Excel テンプレートにデータだけ流し込む

テンプレートを使うメリットのイメージ

現場では、すでに「見た目を作り込んだ Excel」が使われていることが多いです。
罫線、色、ロゴ、説明文、計算式などがすべて入っているファイルです。

こういう場合は、テンプレートの見た目はそのままに、
「特定のセル範囲にだけ毎回データを流し込む」形にすると、現場に馴染みやすくなります。

たとえば、template/sales_report_template.xlsx の「集計」シートで、
B4 セルから店舗×カテゴリの表が始まる、と決めておきます。

openpyxl でテンプレに書き込む例

openpyxl を使うと、「既に存在する Excel を開いて、中身を書き換える」ことができます。

from openpyxl import load_workbook

template_path = TEMPLATE_DIR / "sales_report_template.xlsx"
out_path = OUT_DIR / f"sales_report_{report_date}.xlsx"

wb = load_workbook(template_path)
ws = wb["集計"]

pivot_reset = pivot.reset_index()

start_row = 4
start_col = 2  # B列

for j, col_name in enumerate(pivot_reset.columns, start=start_col):
    ws.cell(row=start_row, column=j, value=str(col_name))

for i, (_, row) in enumerate(pivot_reset.iterrows(), start=start_row + 1):
    for j, val in enumerate(row, start=start_col):
        ws.cell(row=i, column=j, value=val)

wb.save(out_path)
Python

ここで大事なのは、次の3つです。

テンプレ側で「どのシートの」「どのセルから」「どのような表構造で書き込むか」を、最初に仕様として固定しておくこと。
pivot を reset_index して、「1行が1レコード、列名がヘッダー」というシンプルな DataFrame にしてから書くこと。
セルの見た目(罫線・色・フォント)をテンプレ側に持たせておくこと。書き込む側はあくまで値だけ入れる。

このスタイルにしておくと、「レイアウトを変えたい」という要望が来ても、
テンプレ Excel を直すだけで対応できるようになります(コードの変更は最小限で済む)。


つまずきポイントの深掘り(テンプレ変更・日本語・数値と文字・日付)

テンプレが変わったときに壊れないようにする工夫

現実世界では、「テンプレの列位置が変わった」「シート名が変わった」などが起きます。

完全に防ぐのは難しいですが、次のような工夫でダメージを減らせます。

書き込み位置を「セル番地」ではなく「見出し名」から探すようにする。
たとえば、ヘッダーの行を scan して、「店舗」「カテゴリ」「売上」が何列目かをコード側で判断する。

header_row = 4
col_map = {}
for col in range(1, 20):
    val = ws.cell(row=header_row, column=col).value
    if val in ("店舗", "カテゴリ", "売上"):
        col_map[val] = col
Python

これで、「見出し名さえ変わらなければ位置がずれても追従できる」といった設計ができます。

数値が文字列になってしまう問題

openpyxl 経由で書き込むとき、数値に見えても実は文字列として入っているケースがあります。
Excel 上で右寄せと左寄せで見分けがつくあれです。

pandas から to_excel する場合は型を気にする必要はほとんどありませんが、
openpyxl で自前で書く場合は「数値は数値、日付は datetime」として渡すようにします。

from datetime import date

ws["B2"] = 12345           # 数値
ws["C2"] = date(2025, 1, 1)  # 日付オブジェクト
Python

文字列として入れると、Excel 関数やグラフでうまく扱えないことがあります。

日本語フォントや全角文字の扱い

日本語の文字列自体は特に特別扱いせずにそのまま書けますが、
フォントやサイズを制御したい場合は、テンプレ側にスタイルを持たせておく方が楽です。

Python でスタイルを全部組むこともできますが、
初心者のうちは「見た目は Excel 側で、値は Python 側で」と役割をはっきり分けた方が精神的に楽です。


自動化への接続(バッチ化して毎日レポートを吐く)

1本の「レポートバッチ」にまとめるイメージ

ここまでの流れを、1本のスクリプトにまとめておくと、
毎日「python make_report.py」と叩くだけでレポートを吐けるようになります。

ざっくりとした構造は次のようになります。

対象日を決める(例:昨日の日付)。
対象日の CSV を読み込み、pandas で集計。
pivot などレポート用の DataFrame を作る。
新規 Excel へ書き出す、またはテンプレへ書き込んで保存。
ログに成功・失敗・件数・ファイル名などを書き残す。

cron やタスクスケジューラと組み合わせれば、
毎朝決まった時間にレポートが勝手に生成される状態まで持っていけます。


まとめ(「pandasで中身を作り、Excelは入れ物として使う」発想を持つ)

Excel レポート自動作成の肝は、次のような考え方です。

計算や集計は pandas にやらせる。
Excel は「見せるための入れ物」として割り切る。
テンプレ型なら「どのセルに何を入れるか」を仕様として決めておく。
Path と絶対パスでファイルを管理し、毎回同じ場所・同じ名前ルールで出力する。
最初はシンプルに to_excel だけで動かし、徐々に書式設定やテンプレ連携を足していく。

この型さえ掴めば、「日次売上」「月次サマリ」「部署別集計」「KPI ダッシュボード」など、
今 Excel で手作業しているレポートのかなりの部分を、自動化の対象にできます。

タイトルとURLをコピーしました