「毎月、支店や担当者から届くExcelをコピペでまとめるのがしんどい…」「ファイルが増えるたびに集計表を作り直している」

こういう作業、地味に時間がかかりますよね。しかも手作業だと、貼り付け漏れや計算ミスも起きがちです。

この記事では、フォルダに入った複数のExcelファイルをPythonで1つにまとめ、支店×商品のクロス集計をして、見やすいExcelレポートとして保存するところまでを一緒に作っていきます。

難易度:初級〜中級(Pythonの基本文法とpandasのDataFrameを少し触ったことがある方向け)。副業やフリーランスで受ける「Excel集計の自動化」案件でも、そのまま使える基本パターンです🚀

完成イメージと準備

spreadsheet office work
spreadsheet office work / Photo by Kampus Production via Pexels

やることはシンプルで、イメージとしては「フォルダごと読み込む → 縦に積む → ピボットで集計 → Excelに書き出す」の4ステップです。

  • sales フォルダに 売上_東京.xlsx・売上_大阪.xlsx・売上_福岡.xlsx がある
  • 各ファイルの列は「日付・商品・数量・単価」
  • 最後に「集計」「明細」の2シートを持つ 月次売上レポート_2026-09.xlsx を作る

ライブラリは pandas と openpyxl を使います。pandas で .xlsx を読み書きするには openpyxl が別途必要なので、まとめて入れておきましょう。

pip install pandas openpyxl

今回の動作確認は Python 3.13・pandas 3.0.3・openpyxl 3.1.5 で行いました。

ステップ1:練習用のExcelファイルを作る

手元に実データがない方のために、まずはサンプルのExcelを3つ作ります。実際の業務では、ここは「各支店から届いたファイル」に置き換わる部分です。

from pathlib import Path
import pandas as pd

# 支店ごとの売上データ(本来は各支店から届くExcelファイル)
data = {
    "東京": [("2026-09-01", "ノートPC", 2, 128000), ("2026-09-03", "マウス", 10, 2980),
             ("2026-09-10", "モニター", 3, 34800), ("2026-09-18", "ノートPC", 1, 128000)],
    "大阪": [("2026-09-02", "モニター", 2, 34800), ("2026-09-09", "マウス", 6, 2980),
             ("2026-09-15", "キーボード", 4, 8980)],
    "福岡": [("2026-09-05", "キーボード", 5, 8980), ("2026-09-12", "ノートPC", 1, 128000),
             ("2026-09-20", "マウス", 8, 2980)],
}

folder = Path("sales")
folder.mkdir(exist_ok=True)

for branch, rows in data.items():
    df = pd.DataFrame(rows, columns=["日付", "商品", "数量", "単価"])
    df.to_excel(folder / f"売上_{branch}.xlsx", index=False)
    print(f"作成: 売上_{branch}.xlsx({len(df)}行)")
実行結果:サンプルのExcelファイルを作成
実行結果:サンプルのExcelファイルを作成

実行すると sales フォルダに3つのファイルができます。

ステップ2:フォルダ内のExcelをまとめてクロス集計する

ここがこの記事のメインです。ポイントをまとめるとこんな感じです👇

  • Path.glob("売上_*.xlsx") で、対象ファイルを名前のパターンで一括取得
  • ファイル名から支店名を取り出して列に追加(元のExcelに支店列がなくてもOK)
  • pd.concat で縦に1つの表へ
  • pivot_table で「支店 × 商品」の金額合計を作る。margins=True で合計行・合計列も自動で付きます
from pathlib import Path
import pandas as pd

pd.set_option("display.unicode.east_asian_width", True)  # 日本語の列をそろえて表示

folder = Path("sales")
frames = []

# フォルダ内の「売上_〇〇.xlsx」をすべて読み込む
for path in sorted(folder.glob("売上_*.xlsx")):
    df = pd.read_excel(path)
    df["支店"] = path.stem.removeprefix("売上_")  # ファイル名から支店名を取り出す
    frames.append(df)

# 縦に1つの表へまとめる
all_sales = pd.concat(frames, ignore_index=True)
all_sales["金額"] = all_sales["数量"] * all_sales["単価"]

print(f"読み込んだファイル: {len(frames)}件 / 合計 {len(all_sales)}行")

# 支店 × 商品のクロス集計(金額の合計)
summary = all_sales.pivot_table(
    index="支店", columns="商品", values="金額",
    aggfunc="sum", fill_value=0, margins=True, margins_name="合計",
)
print(summary)
実行結果:3ファイルをまとめた支店×商品のクロス集計
実行結果:3ファイルをまとめた支店×商品のクロス集計

実行結果は次のとおりです。東京のノートPCは「2台×128,000円+1台×128,000円=384,000円」で、ちゃんと合っていますね😊

ちなみに display.unicode.east_asian_width の設定を入れないと、日本語の列名で表示がガタガタにずれます。地味ですが、確認作業がぐっと楽になるので入れておくのがおすすめです。

ここが重要です👇 glob のパターンで「余計なファイル」を拾わない

Excelでファイルを開いている間、同じフォルダに ~$売上_東京.xlsx のような一時ファイルができます。*.xlsx で全部拾うと、これを読もうとしてエラーになることがあります。

今回のように 売上_*.xlsx と先頭の文字まで指定しておけば、~$ で始まる一時ファイルは対象外になります。ファイル名のルールを決めておくのが、集計自動化を安定させるコツです。

ステップ3:見やすいExcelレポートとして保存する

集計できたら、Excelに書き出します。pd.ExcelWriter を使うと、1つのファイルに複数シートを書けます。さらに openpyxl で、見出しの色・3桁区切り・列幅を整えます。

次のコードは、ステップ2のコードの末尾にそのまま追記してください。

# ---- ここから追記:集計結果をExcelレポートに書き出す ----
from openpyxl.styles import Font, PatternFill

output = "月次売上レポート_2026-09.xlsx"
with pd.ExcelWriter(output, engine="openpyxl") as writer:
    summary.to_excel(writer, sheet_name="集計")
    all_sales.to_excel(writer, sheet_name="明細", index=False)

    # 見た目を整える(見出しを太字+色付き、金額を3桁区切り、列幅を広げる)
    for ws in writer.book.worksheets:
        for cell in ws[1]:
            cell.font = Font(bold=True, color="FFFFFF")
            cell.fill = PatternFill("solid", fgColor="4472C4")
        for row in ws.iter_rows(min_row=2):
            for cell in row:
                if isinstance(cell.value, (int, float)):
                    cell.number_format = "#,##0"
        for col in ws.columns:
            ws.column_dimensions[col[0].column_letter].width = 14

print(f"保存しました: {output}")
実行結果:保存された月次売上レポートの集計シート(画面イメージ)
実行結果:保存された月次売上レポートの集計シート(画面イメージ)

つまり、writer.book が openpyxl のブック本体なので、pandas で書いた直後にそのまま装飾できる、というわけです。

実行すると、ターミナルにステップ2と同じ集計表が出たあと「保存しました: 月次売上レポート_2026-09.xlsx」と表示されます。保存したファイルを openpyxl で読み直して、「集計」「明細」の2シートができていること、金額に3桁区切りが付いていることを確認しました。

よくあるつまずき⚠️

症状 原因と対処
ImportError: Missing optional dependency 'openpyxl' openpyxl が入っていません。pip install openpyxl で解決します
保存時に PermissionError 出力先の Excel ファイルを開いたまま実行しています。閉じてから再実行しましょう
集計結果が空・行数が少ない ファイル名がパターンと合っていません。print(list(folder.glob("売上_*.xlsx"))) で拾えているか確認します
列名が違って KeyError ファイルごとに「数量」「個数」など表記がバラバラなケース。読み込み直後に df.rename(columns={"個数": "数量"}) でそろえます

これ、実務で一番多いのは最後の「列名のバラつき」です。自動化する前に、提出してもらうExcelのテンプレートをそろえてもらうだけで、トラブルがかなり減りますよ。

まとめ

  • Path.glob でフォルダ内のExcelをパターン指定で一括取得できる
  • pd.concat で縦に積み、pivot_table(margins=True) で合計付きのクロス集計が一発で作れる
  • pd.ExcelWriter で複数シートを書き出し、writer.book から openpyxl で見た目まで整えられる
  • ファイル名と列名のルールを決めておくのが、安定運用のいちばんのコツ

毎月30分かかっていたコピペ集計も、一度スクリプトにしてしまえば実行するだけで終わります。「むずかしそう」を「できそう」に変える第一歩として、ぜひ手元のExcelで試してみてください😊

📚 関連商品・おすすめ書籍

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

もしも

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

初心者に定番のPython入門書

Amazonで見る
実践Claude Code入門―現場で活用するためのAIコーディングの思考法

もしも

実践Claude Code入門―現場で活用するためのAIコーディングの思考法

AIコーディングの現場活用法を学ぶ一冊

Amazonで見る
Python Web開発実践入門 ―― FastAPIによるWebAPI開発と非同期処理

もしも

Python Web開発実践入門 ―― FastAPIによるWebAPI開発と非同期処理

FastAPIでWebAPI開発を実践的に学ぶ

Amazonで見る

※本記事にはアフィリエイトリンクが含まれます。

ABOUT ME
やまちゃん
これまで学生と社会人を合わせて5000人以上にプログラミング学習を指導。 ゼロからイチをわかりやすく解説する専門家として活動しており、本業ではArduinoを用いたIoT開発とロボットプログラミングが専門。 Pythonを用いたアプリ開発、ウェブアプリケーションの開発で業務の効率化をサポートしています。