基礎から学ぶPython入門 90日コース | 業務自動化 - Day 35:Excelファイル一括処理

Python 90日で身につけるPython
スポンサーリンク
スポンサーリンク

Day 35:Excelファイル一括処理で「複数Excel自動集計ツール」を作る

Day 35では、いよいよ 複数のExcelファイルを一括で処理する自動集計ツール を作っていきます。 ここまでの「1つのExcel」「複数シート」の世界から一歩進んで、 「フォルダにある複数のExcelファイルをまとめて集計する」 という、より実務に近い形にしていきます。

目標イメージ:フォルダにある複数Excelをまとめて集計する

やりたいことを言葉で整理する

今回作るツールは、次のような動きをします。

  1. 指定フォルダを確認する
  2. そのフォルダ内にある複数のExcelファイル(例:store_a.xlsx, store_b.xlsx など)を探す
  3. 各Excelファイルの特定シート・特定列(売上など)を読み取る
  4. すべてのファイルの売上データをまとめて集計する
  5. 合計・平均・最大・最小を計算する
  6. 結果を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()
Python

Day 35のまとめ

Day 35では、Excelファイル一括処理として、

  • フォルダ内に複数のExcelファイルを用意し、それらをまとめて対象にする考え方
  • glob を使って .xlsx ファイル一覧を取得する方法
  • 各Excelファイルから特定シート・特定列のデータを読み取る関数の作り方
  • 全ファイルのデータを1つのリストにまとめて、合計・平均・最大・最小を計算する流れ
  • 集計結果を新しい「集計結果Excel」に書き出すテンプレート

をステップバイステップで体験していただきました。

ここまで来ると、 「毎月、複数の店舗・部署から送られてくるExcelを手で集計する」 という作業を、 Pythonでかなりの部分まで自動化できるイメージが持てるはずです。 次のステップでは、条件付き集計やフィルタリングなど、さらに実務寄りのロジックにも踏み込んでいけます。

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