この記事でできること
12枚のシートに同じ操作を手作業で繰り返す。 1月シートを開いて書式変更、2月シートを開いて同じ操作、3月シートを開いて…。12回繰り返して30分。しかも1シートだけ漏れて月次報告で手戻り。毎月やるのに、毎月ヒヤヒヤしている――そんな経験はないだろうか。
この記事のVBAを使えば、全シート(または指定シート)に同じ処理を一括で適用できる。 12シート分の作業が数秒で完了し、漏れもゼロになる。
For Eachループの使い方はシンプル。コピペして実行するだけで、今日から繰り返し地獄を卒業できる。
- VBAで1つのExcel内の全シートに同じ処理を一括実行できる
- 特定のシート(目次・集計など)をスキップして処理できる
- シート数が増えても、コードを変えずにそのまま動く
対象: Excel 2016以降 / Microsoft 365、Windows 10/11
12枚の月別シートに同じ書式変更を手作業で繰り返していた。1枚忘れて上司に指摘されたことも。VBAで一括処理にしてからは、1クリックで全シート完了。あのヒヤヒヤがなくなった。
—
完成イメージ(Before / After)
Before(手動で繰り返し):
- 「1月」シートを開いてヘッダー行を挿入
- 「2月」シートを開いて同じ操作
- 「3月」シートを開いて同じ操作
- …(12回繰り返し)
- 1シートだけ漏れて、あとから手戻り
After(VBAで一括処理):
- マクロを実行
- 全シート(または指定シート)に同じ処理が一括で適用される
- 処理完了のメッセージが表示される
—
12ヶ月分のシートに毎月同じ操作を手動で繰り返していた。1シートでも漏れると月次報告で手戻りになる。毎月やるのに30分以上かかっていたし、1シートだけ漏れて上司に指摘されたこともある。VBAのFor Eachループを使って一括処理するようにしてからは、12シート分の作業が数秒で終わるようになった。この記事で、同じ繰り返し地獄から抜け出してほしい。
同じ操作を12回繰り返すのは、人間がやる仕事じゃない。VBAのループに任せよう。
なお、「複数のファイルを1つに統合する」のとは別のテーマ。ファイル統合は/005を参照。
—
どんな場面で使う?
- 月別12シートにヘッダー行を挿入・書式変更を一括で適用したい
- 全シートのA1セルに同じ文言(「社外秘」など)を一括追記したい
- 部署別シートの集計列を全シートまとめて更新したい
- 特定のシート(目次・集計)だけスキップして、データシートだけ処理したい
—
実行前の準備
バックアップを取る
全シートに一括で変更を加えるため、意図しないシートにも影響する可能性がある。必ずファイルのコピーを別フォルダに保存してから実行する。
Excelをマクロ有効ブック(.xlsm)で保存する
拡張子が .xlsx のままだとマクロが保存できない。
- 「ファイル」→「名前を付けて保存」
- ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
- 保存
—
手順(コピペ → 実行まで約5分)
VBE(コードを書く画面)を開く
- Excelで
Alt + F11を押す - VBE(Visual Basic Editor)が開く
標準モジュールを挿入する
- VBEのメニュー →「挿入」→「標準モジュール」
- 白い画面(コードウィンドウ)が表示される
コードを貼り付けて実行する
- コードウィンドウに、下のコードをそのままコピペする
Alt + F8→ マクロ名を選んで「実行」
ボタンに割り当てれば毎回Alt+F8を押さなくて済む。方法は/013を参照。
—
コード(最小版)– 全シートに同じ処理を一括実行
'============================================================
' ■ 全シートに同じ処理を一括実行(最小版)
' → For Each で全シートをループし、A1セルに値を書き込む
' ※ ThisWorkbook = このマクロが入っているブック
' (ActiveWorkbook とは異なる。通常は ThisWorkbook を使う)
'============================================================
Sub ProcessAllSheets()
Dim ws As Worksheet
Dim count As Long
count = 0
For Each ws In ThisWorkbook.Worksheets
'--- ★ここに各シートで実行したい処理を書く ---
ws.Range("A1").Value = "更新日: " & Format(Date, "yyyy/mm/dd")
ws.Range("A1").Font.Bold = True
count = count + 1
Next ws
MsgBox count & " シートの処理が完了しました。", vbInformation
End Sub
書き換えポイント
| 変数・箇所 | 説明 | 初期値 |
|---|---|---|
'--- ★ここに〜 |
各シートで実行したい処理をここに書く | A1に更新日を書き込み(デモ用) |
コードの流れ
For Each ws In ThisWorkbook.Worksheetsで全シートを1枚ずつ取得ws.Range("A1")のようにws.を付けて 各シートのセルを操作- 処理したシート数をカウントし、完了メッセージを表示
重要: セルを操作するときは必ず ws.Range("A1") のように シート変数を付ける。Range("A1") だけだと、ループ中ずっとアクティブシートのA1を操作してしまう。これが最大の落とし穴。
—
コード(実務版)– シート名で対象を絞り、特定シートをスキップ
実務では「目次」「集計」「マスタ」のようなシートは処理対象から外したい。また、非表示シートも除外したほうが安全。
この仕組みを入れてからは、「目次シートまで書き換えてしまった…」という事故がなくなった。スキップ対象を配列で管理するだけで、安心感がまったく違う。色分けマクロ(/006)も全シートに一括適用できるので、月次報告書の見た目統一が一気に終わる。
'============================================================
' ■ 特定シートをスキップして一括処理(実務版)
' → スキップ対象を配列で定義。非表示シートも除外
' → 処理内容: ヘッダー行の挿入+書式設定(カスタマイズ可能)
'============================================================
Sub ProcessSheetsWithSkip()
'--- ★書き換えポイント1: スキップするシート名 ---
Dim skipSheets As Variant
skipSheets = Array("目次", "集計", "マスタ")
'--- ★ここまで ---
Dim ws As Worksheet
Dim count As Long
count = 0
For Each ws In ThisWorkbook.Worksheets
'--- 非表示シートをスキップ
If ws.Visible <> xlSheetVisible Then GoTo NextSheet
'--- スキップ対象のシートをスキップ
' ※ GoTo NextSheet は VBA でスキップ処理を書く定番パターン。
' ネストが深くならず可読性が高い
If IsInArray(ws.Name, skipSheets) Then GoTo NextSheet
'--- ★書き換えポイント2: 各シートで実行したい処理 ---
'--- 例1: 1行目にヘッダーを挿入
ws.Rows(1).Insert
ws.Range("A1").Value = "月次報告書"
ws.Range("B1").Value = "更新日: " & Format(Date, "yyyy/mm/dd")
'--- 例2: ヘッダー行の書式設定
With ws.Range("A1:E1")
.Font.Bold = True
.Font.Size = 12
.Interior.Color = RGB(0, 112, 192)
.Font.Color = RGB(255, 255, 255)
End With
'--- ★ここまで ---
count = count + 1
NextSheet:
Next ws
MsgBox count & " シートの処理が完了しました。" & vbCrLf & _
"(スキップ対象・非表示シートは除外)", vbInformation
End Sub
'============================================================
' ■ 補助関数: 値が配列に含まれるかチェック
'============================================================
Private Function IsInArray(val As String, arr As Variant) As Boolean
Dim i As Long
For i = LBound(arr) To UBound(arr)
If arr(i) = val Then
IsInArray = True
Exit Function
End If
Next i
IsInArray = False
End Function
書き換えポイント
| 変数・箇所 | 説明 | 初期値 |
|---|---|---|
skipSheets |
スキップするシート名の配列。追加・削除は Array(...) 内を変更するだけ |
Array("目次", "集計", "マスタ") |
'--- ★書き換えポイント2 |
各シートで実行したい処理 | ヘッダー挿入+書式設定(デモ用) |
コードの流れ
- スキップ対象の定義:
Array("目次", "集計", "マスタ")でスキップするシート名を配列で指定 - 非表示チェック:
ws.Visible <> xlSheetVisibleなら処理をスキップ - シート名チェック:
IsInArray関数でスキップ対象に含まれるか確認 - 処理の実行: 対象シートにヘッダー挿入+書式設定
- 完了メッセージ: 処理したシート数を表示
全シートにヘッダーを挿入した後、ボタン(/013)を設置すれば、次回からはワンクリックで一括処理できる。
—
よくある落とし穴5選
1. ws. を付け忘れてアクティブシートだけ処理される
原因: Range("A1").Value = "test" と書くと、ループ中ずっとアクティブシートのA1を操作する。
自分も最初、ws. を付け忘れて12シート分の処理が全部アクティブシートの1枚に上書きされた。「12シート処理完了」と出たのにアクティブシートしか変わっていなくて、しばらく原因が分からなかった。
対策: 必ず ws.Range("A1") のようにシート変数を付ける。ws.Cells, ws.Rows も同様。
2. 目次シートや集計シートまで処理してしまった
自分もこれで痛い目にあった。For Eachで全シートにヘッダー挿入を実行したら、「目次」シートにもヘッダーが入ってしまい、目次のリンクが全部ずれた。戻すのに1時間かかった。目次シートまでぶっ壊すとは思わなかった。
対策: 実務版のように skipSheets 配列でスキップ対象を事前に定義する。
3. 非表示シートも処理されてしまう
原因: For Each ws In Worksheets は非表示シートも含む。非表示にしていたマスタシートが書き換えられる可能性がある。
対策: ws.Visible <> xlSheetVisible でスキップする。実務版コードには組み込み済み。
4. シート名の全角・半角やスペースが一致しない
原因: If ws.Name = "目次" と書いたが、実際のシート名が「目次 」(末尾に半角スペースあり)だった。
対策: If Trim(ws.Name) = "目次" のように Trim(文字列の前後のスペースを除去する関数)でスペースを除去してから比較する。
5. ループ中にシートを追加/削除するとエラーになる
原因: For Each ループの途中でシートのコレクションを変更すると、VBAが混乱してエラーが出る。
対策: ループ中はシートの追加・削除をしない。必要なら、ループ前にシート名を配列に格納し、配列でループする。
VBAで複数シート処理中に特定シートだけエラーになるときの対処法
「一部のシートだけ処理されない」という場合、原因はシート名にスペースや特殊文字が含まれているか、グラフシートが混在していることだ。If ws.Type = xlWorksheet Then で通常のワークシートだけを対象に絞れば、グラフシートでのエラーを回避できる。
VBAのFor Eachループで処理順がバラバラになるときの対処法
「シートの処理順が想定と違う」という場合、原因はFor Eachがシートのインデックス順で処理するため、シートの並び順が変わると処理順も変わることだ。処理順を固定したい場合は、シート名を配列に格納して For i = 1 To UBound(arr) のインデックスループに切り替えれば解決する。
—
FAQ
Q1: 特定のシートだけを処理したい(全シートではなく)
スキップではなく対象シートを指定したい場合は、対象シート名を配列に入れて一致チェックする:
Dim targetSheets As Variant
targetSheets = Array("1月", "2月", "3月")
For Each ws In ThisWorkbook.Worksheets
If IsInArray(ws.Name, targetSheets) Then
' 対象シートの処理
ws.Range("A1").Value = "処理済み"
End If
Next ws
Q2: 処理の進捗をリアルタイムで確認したい
ステータスバーに進捗を表示する:
Dim total As Long
total = ThisWorkbook.Worksheets.Count
For Each ws In ThisWorkbook.Worksheets
count = count + 1
Application.StatusBar = "処理中... " & count & " / " & total & " シート"
' --- 処理 ---
Next ws
Application.StatusBar = False ' ステータスバーを元に戻す
Q3: 全シートに色分けを一括適用したい
ループ内で色分け処理を呼び出す。色分けの方法は/006を参照。
For Each ws In ThisWorkbook.Worksheets
Call ColorByValue(ws) ' 各シートを引数で渡す
Next ws
Q4: 全シートのデータを1つのシートに集約したい
これは「複数シートの一括処理」とは別のテーマ。複数Excelファイルを1つに統合する方法は/005を参照。1ファイル内のシート統合もループで可能だが、処理内容が複雑になるためカスタマイズの範囲。
Q5: ボタン1つで全シート処理を実行したい
/013で、ProcessSheetsWithSkip をボタンに割り当てる。シート上に「全シート一括処理」ボタンを置けば、同僚にも簡単に使ってもらえる。
—
まとめ
For Each ws In ThisWorkbook.Worksheetsで全シートをループできるws.Range("A1")のようにシート変数を付けないと、アクティブシートだけ処理される(最大の落とし穴)- スキップ対象は配列で管理し、非表示シートも除外すると安全
- シート数が増えてもコードの変更は不要。ループが自動で全シートを処理する
関連記事
- /005 — 複数Excelファイルを1つに統合する方法。複数ファイルの統合はこちら。1ファイル内の複数シート処理は本記事
- /006 — セルの値に応じて行を自動色分けする方法。全シートに色分けを一括適用する応用
- /013 — マクロをボタン1つで実行する方法。一括処理マクロをボタンに割り当て
- /043 — シートを別ブックにコピー・移動する方法。シート単位でファイルを分割したい場合に
- /069 — シート名の取得・一括変更・存在チェックする方法。シート名を動的に扱いたい場合に
—
次にやりたくなること
- /043 — シートを別ブックにコピー。月別シートを個別のExcelファイルに分割して配布したい場合に。一括処理でデータを整えた後、シートごとにファイルを分けるワークフローが作れる
- /069 — シート名の取得・変更。シート名を動的に取得して処理に使ったり、一括でリネームしたりできる。シート一括処理と組み合わせると、より柔軟な自動化が可能になる
- /006 — 行の自動色分け。全シートにステータス別の色分けを一括適用したい場合に
- /023 — セルの書式を一括変更。全シートのフォントや罫線を一括で統一したい場合に
- /032 — 最終行・最終列の取得。シートごとにデータ範囲が異なるときに正確に処理範囲を取得したい場合に
—


コメント