Day 35:Excelファイル一括処理で「複数Excel自動集計ツール」を作る
Day 35では、いよいよ 複数のExcelファイルを一括で処理する自動集計ツール を作っていきます。 ここまでの「1つのExcel」「複数シート」の世界から一歩進んで、 「フォルダにある複数のExcelファイルをまとめて集計する」 という、より実務に近い形にしていきます。
目標イメージ:フォルダにある複数Excelをまとめて集計する
やりたいことを言葉で整理する
今回作るツールは、次のような動きをします。
- 指定フォルダを確認する
- そのフォルダ内にある複数のExcelファイル(例:
store_a.xlsx,store_b.xlsxなど)を探す - 各Excelファイルの特定シート・特定列(売上など)を読み取る
- すべてのファイルの売上データをまとめて集計する
- 合計・平均・最大・最小を計算する
- 結果を1つの「集計結果Excel」に書き出す
つまり、「ファイル単位の集計」ではなく「フォルダ単位の集計」 を行うツールです。
サンプルデータの準備:複数Excelファイルを作る
まずは、説明用に複数のExcelファイルを作るコードを書きます。
# day35_setup.py
from openpyxl import Workbook
import os
def create_sample_excels(output_dir="excel_data"):
"""複数の店舗別Excelファイルを作成する関数です。"""
os.makedirs(output_dir, exist_ok=True)
# 店舗A
wb_a = Workbook()
ws_a = wb_a.active
ws_a.title = "Sales"
ws_a["A1"] = "日付"; ws_a["B1"] = "売上"
ws_a["A2"] = "2024-01-01"; ws_a["B2"] = 1200
ws_a["A3"] = "2024-01-02"; ws_a["B3"] = 800
ws_a["A4"] = "2024-01-03"; ws_a["B4"] = 1500
wb_a.save(os.path.join(output_dir, "store_a.xlsx"))
# 店舗B
wb_b = Workbook()
ws_b = wb_b.active
ws_b.title = "Sales"
ws_b["A1"] = "日付"; ws_b["B1"] = "売上"
ws_b["A2"] = "2024-01-01"; ws_b["B2"] = 900
ws_b["A3"] = "2024-01-02"; ws_b["B3"] = 1100
ws_b["A4"] = "2024-01-03"; ws_b["B4"] = 700
wb_b.save(os.path.join(output_dir, "store_b.xlsx"))
# 店舗C
wb_c = Workbook()
ws_c = wb_c.active
ws_c.title = "Sales"
ws_c["A1"] = "日付"; ws_c["B1"] = "売上"
ws_c["A2"] = "2024-01-01"; ws_c["B2"] = 500
ws_c["A3"] = "2024-01-02"; ws_c["B3"] = 1300
ws_c["A4"] = "2024-01-03"; ws_c["B4"] = 900
wb_c.save(os.path.join(output_dir, "store_c.xlsx"))
print(f"{output_dir} フォルダに複数の店舗別Excelファイルを作成しました。")
if __name__ == "__main__":
create_sample_excels()
Pythonこのコードを実行すると、excel_data フォルダに3つのExcelファイルが作成されます。
フォルダ内のExcelファイルを一覧取得する
globで .xlsx ファイルを探す
複数Excelを一括処理するためには、まず「どのファイルがあるか」を知る必要があります。
import glob
import os
def list_excel_files(directory="excel_data"):
"""指定フォルダ内のExcelファイル一覧を取得する関数です。"""
pattern = os.path.join(directory, "*.xlsx") # .xlsx ファイルを対象にします。
files = glob.glob(pattern)
print("=== 対象Excelファイル一覧 ===")
for f in files:
print(" -", f)
return files
Pythonここでのポイントは、
glob.glob()で「パターンに合うファイル」をまとめて取得していること*.xlsxというパターンで、Excelファイルだけを対象にしていること
です。
各Excelファイルから売上データを読み取る
「SalesシートのB列」を読み取る関数
from openpyxl import load_workbook
def read_sales_from_file(filepath):
"""1つのExcelファイルから売上データを読み取る関数です。"""
wb = load_workbook(filepath)
ws = wb["Sales"] # 今回は 'Sales' シートがある前提です。
sales_values = []
# 2行目〜4行目のB列(売上)を読み取ります。
for row in range(2, 5):
value = ws.cell(row=row, column=2).value # B列
if isinstance(value, (int, float)):
sales_values.append(value)
print(f"{os.path.basename(filepath)} から売上データを読み取りました: {sales_values}")
return sales_values
Pythonここでのポイントは、
- 1ファイル単位で「売上データのリスト」を返す関数にしていること
- シート名や列番号を固定しておくことで、処理をシンプルにしていること
です。
複数Excelファイルの売上をまとめて集計する
全ファイルの売上を1つのリストに集める
def collect_all_sales(directory="excel_data"):
"""フォルダ内の複数Excelファイルから売上データをまとめて取得する関数です。"""
files = list_excel_files(directory)
all_sales = []
for filepath in files:
sales = read_sales_from_file(filepath)
all_sales.extend(sales) # リストを結合します。
print("=== 全ファイルの売上データ ===")
print(all_sales)
return all_sales
Pythonここでのポイントは、
list_excel_files()で取得したファイル一覧をループしていること- 各ファイルから取得した売上リストを
extend()でまとめていること - 「ファイルごとの売上」ではなく「全ファイルの売上」を1つのリストにしていること
です。
合計・平均・最大・最小を計算する
集計関数(Day 34の応用)
def calculate_statistics(values):
"""売上リストから合計・平均・最大・最小を計算する関数です。"""
if not values:
return {"sum": 0, "avg": 0, "max": 0, "min": 0}
total = sum(values)
avg = total / len(values)
max_value = max(values)
min_value = min(values)
print("=== 集計結果 ===")
print(f"合計: {total}")
print(f"平均: {avg}")
print(f"最大: {max_value}")
print(f"最小: {min_value}")
return {"sum": total, "avg": avg, "max": max_value, "min": min_value}
Python集計結果を「集計結果Excel」に書き出す
新しいExcelファイルに結果を書く
from openpyxl import Workbook
def write_summary_excel(stats, output_path="summary.xlsx"):
"""集計結果を新しいExcelファイルに書き出す関数です。"""
wb = Workbook()
ws = wb.active
ws.title = "Summary"
# ヘッダー
ws["A1"] = "項目"
ws["B1"] = "値"
# 集計結果
ws["A2"] = "合計"; ws["B2"] = stats["sum"]
ws["A3"] = "平均"; ws["B3"] = stats["avg"]
ws["A4"] = "最大"; ws["B4"] = stats["max"]
ws["A5"] = "最小"; ws["B5"] = stats["min"]
wb.save(output_path)
print(f"集計結果を {output_path} に保存しました。")
Pythonここでのポイントは、
- 元データとは別のExcelファイル(
summary.xlsx)に結果を書いていること - 「項目」と「値」の2列構成でシンプルにまとめていること
です。
完成版:複数Excel自動集計ツール(テンプレート)
最後に、ここまでの関数を1つのスクリプトにまとめた「複数Excel自動集計ツール」のテンプレートを示します。
# day35_multi_excel_aggregate.py
from openpyxl import Workbook, load_workbook
import os
import glob
def create_sample_excels(output_dir="excel_data"):
os.makedirs(output_dir, exist_ok=True)
wb_a = Workbook()
ws_a = wb_a.active
ws_a.title = "Sales"
ws_a["A1"] = "日付"; ws_a["B1"] = "売上"
ws_a["A2"] = "2024-01-01"; ws_a["B2"] = 1200
ws_a["A3"] = "2024-01-02"; ws_a["B3"] = 800
ws_a["A4"] = "2024-01-03"; ws_a["B4"] = 1500
wb_a.save(os.path.join(output_dir, "store_a.xlsx"))
wb_b = Workbook()
ws_b = wb_b.active
ws_b.title = "Sales"
ws_b["A1"] = "日付"; ws_b["B1"] = "売上"
ws_b["A2"] = "2024-01-01"; ws_b["B2"] = 900
ws_b["A3"] = "2024-01-02"; ws_b["B3"] = 1100
ws_b["A4"] = "2024-01-03"; ws_b["B4"] = 700
wb_b.save(os.path.join(output_dir, "store_b.xlsx"))
wb_c = Workbook()
ws_c = wb_c.active
ws_c.title = "Sales"
ws_c["A1"] = "日付"; ws_c["B1"] = "売上"
ws_c["A2"] = "2024-01-01"; ws_c["B2"] = 500
ws_c["A3"] = "2024-01-02"; ws_c["B3"] = 1300
ws_c["A4"] = "2024-01-03"; ws_c["B4"] = 900
wb_c.save(os.path.join(output_dir, "store_c.xlsx"))
print(f"{output_dir} フォルダにサンプルExcelを作成しました。")
def list_excel_files(directory="excel_data"):
pattern = os.path.join(directory, "*.xlsx")
files = glob.glob(pattern)
print("=== 対象Excelファイル一覧 ===")
for f in files:
print(" -", f)
return files
def read_sales_from_file(filepath):
wb = load_workbook(filepath)
ws = wb["Sales"]
sales_values = []
for row in range(2, 5):
value = ws.cell(row=row, column=2).value
if isinstance(value, (int, float)):
sales_values.append(value)
print(f"{os.path.basename(filepath)}: {sales_values}")
return sales_values
def collect_all_sales(directory="excel_data"):
files = list_excel_files(directory)
all_sales = []
for filepath in files:
sales = read_sales_from_file(filepath)
all_sales.extend(sales)
print("=== 全ファイルの売上データ ===")
print(all_sales)
return all_sales
def calculate_statistics(values):
if not values:
return {"sum": 0, "avg": 0, "max": 0, "min": 0}
total = sum(values)
avg = total / len(values)
max_value = max(values)
min_value = min(values)
print("=== 集計結果 ===")
print(f"合計: {total}")
print(f"平均: {avg}")
print(f"最大: {max_value}")
print(f"最小: {min_value}")
return {"sum": total, "avg": avg, "max": max_value, "min": min_value}
def write_summary_excel(stats, output_path="summary.xlsx"):
wb = Workbook()
ws = wb.active
ws.title = "Summary"
ws["A1"] = "項目"
ws["B1"] = "値"
ws["A2"] = "合計"; ws["B2"] = stats["sum"]
ws["A3"] = "平均"; ws["B3"] = stats["avg"]
ws["A4"] = "最大"; ws["B4"] = stats["max"]
ws["A5"] = "最小"; ws["B5"] = stats["min"]
wb.save(output_path)
print(f"集計結果を {output_path} に保存しました。")
def main():
# 1. サンプルExcelを作成(実務では既存ファイルを使う想定です)
create_sample_excels()
# 2. 複数Excelから売上データを収集
all_sales = collect_all_sales()
# 3. 集計(合計・平均・最大・最小)
stats = calculate_statistics(all_sales)
# 4. 集計結果を新しいExcelに書き出し
write_summary_excel(stats)
if __name__ == "__main__":
main()
PythonDay 35のまとめ
Day 35では、Excelファイル一括処理として、
- フォルダ内に複数のExcelファイルを用意し、それらをまとめて対象にする考え方
globを使って.xlsxファイル一覧を取得する方法- 各Excelファイルから特定シート・特定列のデータを読み取る関数の作り方
- 全ファイルのデータを1つのリストにまとめて、合計・平均・最大・最小を計算する流れ
- 集計結果を新しい「集計結果Excel」に書き出すテンプレート
をステップバイステップで体験していただきました。
ここまで来ると、 「毎月、複数の店舗・部署から送られてくるExcelを手で集計する」 という作業を、 Pythonでかなりの部分まで自動化できるイメージが持てるはずです。 次のステップでは、条件付き集計やフィルタリングなど、さらに実務寄りのロジックにも踏み込んでいけます。
