概要(「決まったExcel」ならPythonで一気に集計できる)
毎月・毎店舗・毎担当者から、同じ形式のExcelが集まってきて、
それを手でコピペして集計していませんか。
「テンプレが決まっているExcel」なら、Python+pandasで
- 複数ファイルの読み込み
- 必要なセル・シートだけの取得
- 1枚の集計表への結合
- 集計結果をExcelテンプレに自動出力
までを一気に自動化できます。
ここでは「毎月の売上テンプレを自動集計する」という具体的な例で、
仕組みと実装を、初心者向けにかみ砕いて説明します。
基本の流れ(テンプレ分析 → 読み込み → 結合 → 集計 → 書き出し)
どんなテンプレを想定するか
例えば、こんなExcelファイルを毎店舗から回収しているとします。
- ファイル名:
store_A.xlsx,store_B.xlsxなど - シート名:
入力(全店舗共通) - 行1: 項目名(ヘッダー)
- A列: 日付
- B列: 商品カテゴリ
- C列: 売上金額
イメージ:
| 日付 | カテゴリ | 売上 |
|---|---|---|
| 2025/01/01 | A | 10000 |
| 2025/01/01 | B | 8000 |
| … | … | … |
この「同じ形」さえ守られていれば、Pythonからは非常に扱いやすくなります。
必要なライブラリ
Python側では主に pandas を使います。Excelを扱うときは、エンジンとして openpyxl を一緒に入れておくのが無難です。
pip install pandas openpyxl
複数のテンプレExcelを読み込んで「縦にくっつける」
1ファイルを pandas で読む基本
まずは1店舗分を読み込むイメージから。
import pandas as pd
path = "data/store_A.xlsx"
df = pd.read_excel(
path,
sheet_name="入力", # シート名を指定
engine="openpyxl" # ほぼおまじない
)
print(df.head())
Pythonここで大事なのは「テンプレのどのシート・どの行から・どの列を読むか」を、最初にしっかり決めておくことです。
もし1行目がタイトルで、2行目からヘッダー、3行目からデータ…などの場合は、ヘッダーの行を指定できます。
df = pd.read_excel(
path,
sheet_name="入力",
header=1 # 0始まりなので、「2行目がヘッダー」の意味
)
Python複数ファイルをループでまとめて読み込む
次に、フォルダ内にある複数のExcelファイルを全部読むパターンです。
globで「*.xlsx」を拾って、それをforループで回します。
from pathlib import Path
import pandas as pd
folder = Path("data") # Excelが入っているフォルダ
files = sorted(folder.glob("store_*.xlsx"))
all_list = []
for f in files:
df = pd.read_excel(f, sheet_name="入力", engine="openpyxl")
df["店舗"] = f.stem.replace("store_", "") # ファイル名から店舗名を付与
all_list.append(df)
all_data = pd.concat(all_list, ignore_index=True)
print(all_data.head())
Pythonポイントは、ファイルごとの差(店舗名や担当者名)を、
「列として追加しておく」ことです。後の集計で効きます。
pandas で集計(groupby)して「欲しい形」にする
店舗×カテゴリ×月ごとの売上集計
例えば「店舗別・カテゴリ別・月別の売上合計」が欲しいとします。
日付から「月」を取り出し、groupbyで集計します。
all_data["日付"] = pd.to_datetime(all_data["日付"])
all_data["月"] = all_data["日付"].dt.to_period("M").dt.to_timestamp()
summary = (
all_data
.groupby(["店舗", "月", "カテゴリ"], as_index=False)["売上"]
.sum()
)
print(summary.head())
Pythonここで重要なのは
- 日付列を必ず datetime 型に変換する(to_datetime)
- groupby のキーを「どの粒度で集計したいか」を意識して決める
という2点です。
集計結果を「表形式」に整える(ピボット)
店舗を行、カテゴリを列、セルに売上…というExcelらしい形にしたいときは、pivot_table を使います。
pivot = summary.pivot_table(
index=["店舗", "月"], # 行方向
columns="カテゴリ", # 列方向
values="売上", # セルの値
aggfunc="sum", # 念のため
fill_value=0 # 欠損は0で埋める
)
print(pivot.head())
Pythonこれで、「店舗と月の組み合わせごとに、カテゴリ別売上が横一列に並んだ表」ができます。
集計結果を Excel テンプレに自動出力する
「集計結果用テンプレ」を用意するイメージ
多くの現場では、集計用のExcelにもフォーマット(罫線や色、固定セルなど)が決まっています。
例:
template_summary.xlsxというテンプレファイルがあり、集計シートの B3 から、店舗×カテゴリの表を書き込む
とします。
一番シンプルな「テンプレを無視して上書き」パターン
フォーマットにこだわらず、「純粋な集計結果だけをExcelに出したい」なら、この方法が一番簡単です。
pivot.to_excel("output/summary_simple.xlsx", sheet_name="集計")
Pythonただしこの方法だと、テンプレの罫線やフォーマットは全て無視され、pivotの内容だけが書かれます。
openpyxl を使って「テンプレに書き込む」
テンプレの装飾を保ちつつ、中身だけ差し替えたい場合は、openpyxl で Workbook を開き、そのセルに pandas の値を流し込みます。
from openpyxl import load_workbook
# テンプレを読み込む
wb = load_workbook("template/template_summary.xlsx")
ws = wb["集計"]
# pivot を普通の DataFrame に整える(マルチインデックスをリセット)
pivot_reset = pivot.reset_index()
start_row = 3
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("output/summary_from_template.xlsx")
Pythonここでポイントになるのは次の3つです。
- 「テンプレのセル位置」をコードで固定しておく(start_row, start_col)
- マルチインデックス(店舗・月とカテゴリ)を一度 reset_index して、
「列見出し」と「値」をシンプルな形に戻してから書き込む ws.cell(row=..., column=...)で1セルずつ書くので、
罫線や色など「セルの見た目」はテンプレ側が維持される
重要な設計ポイントの深掘り(失敗しやすい所を先に潰す)
1. テンプレの変更に耐えられるようにする
現場あるあるとして、「Excelテンプレが途中で変わる」があります。
列名が変わる、列の順番が変わる、シート名が変わる…。
防ぐには、
- 読み込み時は「列の順番」ではなく「列名」で指定する
- シート名は一定にしてもらう(変更時はコードも変更)
- 列名が変わったら、読み込み直後に rename で統一する
という運用・コードの両面からの対策が効きます。
df = pd.read_excel(path, sheet_name="入力", engine="openpyxl")
df = df.rename(columns={
"売上": "売上金額", # 古いテンプレにも対応
"売上金額": "売上金額"
})
Python2. データ型(数値・文字・日付)を必ず揃える
Excel由来のデータは、同じ列なのに
- 数値と文字列が混ざる
- 日付が文字のまま入っている
などが頻発します。これをそのまま集計すると、
「思ったように groupby されない」「ソートが変になる」などの事故に繋がります。
対策としては、
- 数値列は
pd.to_numeric(errors="coerce")で数値化+変換不可は NaN - 日付列は
pd.to_datetime(errors="coerce")で datetime 化 - 集計前に
dtypesを確認して、意図通りかチェック
を型として徹底すると安心です。
df["売上"] = pd.to_numeric(df["売上"], errors="coerce")
df["日付"] = pd.to_datetime(df["日付"], errors="coerce")
Python3. ファイル名からメタ情報を取る設計
店舗名・拠点名・月などが、Excelの中にも書いてある場合でも、
「ファイル名からも取っておく」と後で助かります。
例)store_A_2025-01.xlsx から、店舗A・2025-01月を取る。
import re
f = Path("data/store_A_2025-01.xlsx")
m = re.match(r"store_(.+)_(\d{4}-\d{2})\.xlsx", f.name)
store = m.group(1)
month = m.group(2)
PythonExcel側の入力ミス(店舗名のタイプミスなど)があっても、
ファイル名からの情報を信頼するようにしておけば、
データの品質が安定しやすくなります。
4. フォルダ構成とログ出力
実運用では、
data/raw:元のExceldata/processed:処理済みの中間ファイル(必要なら)output:集計結果・レポートExceltemplate:テンプレ置き場
のようにフォルダを分けておくとトラブルが少なくなります。
さらに、「どのファイルを読んで」「何件レコードがあり」「エラーはあったか」
を print やログに出しておくと、後から原因追跡がしやすくなります。
まとめ(「テンプレの形を固定 → pandasで読み込み → groupby → Excelへ書き込み」を型にする)
Excelテンプレを使った自動集計の肝は、
- テンプレのシート名・列名・セル位置を“仕様”として固定する
- pandas で「複数ファイルを縦結合→groupby→pivot」で欲しい形に整える
- 集計結果を
to_excelか、openpyxl経由でテンプレに書き戻す - データ型(数値・日付)と、ファイル名からのメタ情報をきちんと揃える
この型さえ押さえれば、毎月の「地獄のコピペ作業」を、
ワンクリックや1コマンドで終わらせることができます。

