【実測】Excelの12シート(2,400行)を1枚にまとめる、Pythonなら平均4.7秒|コピペで動くスクリプト付き
月別の12シート(合計2,400行)に分かれたExcelの売上表を、Pythonで1枚のシートに結合したところ、3回実測の平均で4.737秒でした。一番遅かった1回目でも6.494秒で、コピペ1回でスクリプトを用意すれば、あとは実行するだけで毎回数秒で終わります。
この記事では、実際に使ったスクリプトの全文と使い方、3回分の実測結果、つまずきやすいポイントまで、すべて手元で検証した内容だけを書きます。
背景:月別シートの手作業集計はつらい
「1月」「2月」…「12月」とシートが月別に分かれたブックは、月次の入力には便利ですが、年間集計をしようとした瞬間に困ります。ピボットテーブル(ドラッグ操作で集計表を作るExcelの機能)は基本的に1枚の表を元データにするため、まず12シートを1枚にまとめる作業が必要になるからです。
手作業でやる場合は「シートを開く→データ範囲を選択→コピー→まとめシートの末尾に貼り付け」を12回繰り返すことになります。1シートあたり1〜2分かかるとすれば全体で12〜24分程度(この時間は実測ではなく推定です)。しかも貼り付け位置のずれや、どの月まで貼ったか分からなくなるといったミスが起きやすい作業です。毎月・毎年発生するなら、自動化の価値は十分あります。
検証環境とデータ内容
実測に使った環境とデータは次のとおりです。
- OS: Windows 11 Pro(ビルド 10.0.26200)
- Python: 3.12.10(venv環境)
- pandas: 3.0.5 / openpyxl: 3.1.5
- 入力ファイル: 売上_2025.xlsx(シート「1月」〜「12月」の12枚、各200行、合計2,400行)
- 列構成: 日付/商品名/数量/単価/金額の5列
- データ内容: 日本語の文房具20品目からランダム生成(乱数シード44で固定)、日付は各月の範囲内
なお、OneDrive同期フォルダ内で実行すると同期処理が計測に影響する可能性があるため、実行はローカルのTempフォルダ配下で行いました。
スクリプト全文と使い方
以下が実測に使ったスクリプトの全文です。時間計測のために3回実行するようにしていますが、実務ではこのまま実行して問題ありません(結果のファイルは同じものが上書きされるだけです)。
# -*- coding: utf-8 -*-
"""Excelブック内の全シート(12ヶ月分)を1枚に結合して保存し、所要時間を実測する"""
import time
import pandas as pd
# このスクリプトをExcelファイルと同じフォルダに置いて実行してください
INPUT_FILE = "売上_2025.xlsx" # 結合したいブック(シート「1月」〜「12月」)
OUTPUT_FILE = "まとめ.xlsx" # 結合結果の保存先
def merge_all_sheets():
# sheet_name=None で全シートを一括読み込み(シート名→DataFrameの辞書が返る)
sheets = pd.read_excel(INPUT_FILE, sheet_name=None)
frames = []
for sheet_name, df in sheets.items():
df["元シート名"] = sheet_name # どのシート由来か分かるように列を追加
frames.append(df)
merged = pd.concat(frames, ignore_index=True)
merged.to_excel(OUTPUT_FILE, index=False)
return len(merged), len(sheets)
if __name__ == "__main__":
times = []
for i in range(3):
start = time.perf_counter()
total_rows, sheet_count = merge_all_sheets()
elapsed = time.perf_counter() - start
times.append(elapsed)
print(f"{i + 1}回目: {elapsed:.3f}秒 (シート{sheet_count}枚 → {total_rows}行)")
print(f"平均: {sum(times) / len(times):.3f}秒")
使い方(3ステップ)
- 上のコードを「merge.py」などの名前で保存し、結合したいExcelファイルと同じフォルダに置きます
- 冒頭の
INPUT_FILEを自分のファイル名に書き換えます - コマンドプロンプト(Windowsの黒い画面)でそのフォルダに移動し、
python merge.pyと入力して実行します
実行が終わると、同じフォルダに「まとめ.xlsx」が作られます。
sheet_name=None の意味
ポイントは pd.read_excel(INPUT_FILE, sheet_name=None) の1行です。通常はシート名を1つ指定して読み込みますが、sheet_name=None を指定すると「全シートをまとめて読み込む」という意味になり、「シート名→表データ」の辞書(名前と中身のペアの一覧)が返ってきます。あとはそれを順番につなげるだけです。
もう1つの工夫が「元シート名」列の追加です。結合後の表に「1月」「2月」…という列が付くので、どの行がどの月のデータか結合後も追跡でき、そのままピボットテーブルの元データとして使えます。
実測結果:3回の計測
同じ処理を3回連続で実行した結果です。
| 実行回 | 所要時間 |
|---|---|
| 1回目 | 6.494秒 |
| 2回目 | 4.001秒 |
| 3回目 | 3.715秒 |
| 平均 | 4.737秒 |
1回目だけ約1.7倍遅いのは、初回のファイル読み込み(ファイルキャッシュが効く前のディスクアクセス)の影響とみられます。2回目以降は約3.7〜4.0秒で安定しました。
処理時間の内訳としては、Excelファイルの読み込みと書き込み(I/O)が支配的です。12シート・2,400行という決して大きくないデータでも1回あたり約4秒かかるのは、Excel形式の読み書きにそれだけ手間がかかるためです。それでも、手作業の推定12〜24分と比べれば十分実用的な速さです。
出力結果の検証
「速い」だけでは意味がないので、出力された「まとめ.xlsx」の中身もopenpyxl(ExcelファイルをPythonで直接読み書きするライブラリ)で検証しました。
- 総行数は2,401行(ヘッダ1行+データ2,400行)で期待どおり
- 列は「日付/商品名/数量/単価/金額/元シート名」の6列
- 「元シート名」の内訳は1月〜12月が各200行ちょうど
- 全2,400行で「金額=数量×単価」が一致(不一致0行)
- 「日付の月」と「元シート名の月」も全行一致(不一致0行)
- 並び順はブック内のシート順(1月→12月)が保持され、先頭行は2025/01/01、最終行は2025/12/31
pandas 3.0.5では sheet_name=None が返す辞書がブック内のシート順を保つため、月順に並べ替える処理を書かなくても月順のまま結合されました。
つまずきポイント
出力ファイルを開いたまま実行しない
「まとめ.xlsx」をExcelで開いたままスクリプトを再実行すると、Windowsではファイルが使用中のため保存に失敗し、エラー(PermissionError)で止まります。再実行する前に、出力ファイルは必ず閉じてください。
シートごとに列名が違う場合の挙動
このスクリプトは列名を手がかりに結合します。もしシートによって列名が違う(例:あるシートだけ「金額」が「売上金額」になっている)と、エラーにはならず、別々の列として横に並び、該当しないシートの行は空欄になります。一見成功したように見えて集計が狂う原因になるので、実行前に全シートの1行目(列名)が揃っているか確認してください。今回の検証データは12シートとも同じ列構成だったため、この問題は起きていません。
1回目の実行は遅めに出る
前述のとおり、1回目は6.494秒と2回目以降より遅くなりました。初回だけ遅くても異常ではないので、「思ったより遅い?」と感じたらもう一度実行してみてください。
まとめ
- 月別12シート・2,400行の結合は、3回実測の平均4.737秒(最遅でも6.494秒)
sheet_name=Noneで全シート一括読み込み+「元シート名」列の追加が実用上のポイント- 出力は総行数・月別内訳・金額の整合性まで検証し、不一致0行を確認
- 出力ファイルを開いたままの再実行と、シート間の列名の不一致には注意
なお、以前の記事で検証したCSVファイル100個の結合は平均3.8秒でした。ファイル数がずっと多いのにExcel12シートと同水準の時間で済んでいることからも、Excel形式の読み書きは相対的に時間がかかることが分かります。とはいえ、どちらも「コピペ1回でスクリプトを用意すれば、あとは数秒」の世界です。月末の集計作業が憂うつな方は、まず手元のファイルのコピーで試してみてください。
コメント
コメントを投稿