【VBA】複数シートに同じ処理を一括実行する方法(コピペOK)

VBA
スポンサーリンク
スポンサーリンク

この記事でできること

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. 「1月」シートを開いてヘッダー行を挿入
  2. 「2月」シートを開いて同じ操作
  3. 「3月」シートを開いて同じ操作
  4. …(12回繰り返し)
  5. 1シートだけ漏れて、あとから手戻り

After(VBAで一括処理):

  1. マクロを実行
  2. 全シート(または指定シート)に同じ処理が一括で適用される
  3. 処理完了のメッセージが表示される

12ヶ月分のシートに毎月同じ操作を手動で繰り返していた。1シートでも漏れると月次報告で手戻りになる。毎月やるのに30分以上かかっていたし、1シートだけ漏れて上司に指摘されたこともある。VBAのFor Eachループを使って一括処理するようにしてからは、12シート分の作業が数秒で終わるようになった。この記事で、同じ繰り返し地獄から抜け出してほしい。

同じ操作を12回繰り返すのは、人間がやる仕事じゃない。VBAのループに任せよう。

なお、「複数のファイルを1つに統合する」のとは別のテーマ。ファイル統合は/005を参照。

どんな場面で使う?

  • 月別12シートにヘッダー行を挿入・書式変更を一括で適用したい
  • 全シートのA1セルに同じ文言(「社外秘」など)を一括追記したい
  • 部署別シートの集計列を全シートまとめて更新したい
  • 特定のシート(目次・集計)だけスキップして、データシートだけ処理したい

実行前の準備

バックアップを取る

全シートに一括で変更を加えるため、意図しないシートにも影響する可能性がある。必ずファイルのコピーを別フォルダに保存してから実行する。

Excelをマクロ有効ブック(.xlsm)で保存する

拡張子が .xlsx のままだとマクロが保存できない。

  1. 「ファイル」→「名前を付けて保存」
  2. ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
  3. 保存

手順(コピペ → 実行まで約5分)

VBE(コードを書く画面)を開く

  1. Excelで Alt + F11 を押す
  2. VBE(Visual Basic Editor)が開く

標準モジュールを挿入する

  1. VBEのメニュー →「挿入」→「標準モジュール」
  2. 白い画面(コードウィンドウ)が表示される

コードを貼り付けて実行する

  1. コードウィンドウに、下のコードをそのままコピペする
  2. 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に更新日を書き込み(デモ用)

コードの流れ

  1. For Each ws In ThisWorkbook.Worksheets で全シートを1枚ずつ取得
  2. ws.Range("A1") のように ws.を付けて 各シートのセルを操作
  3. 処理したシート数をカウントし、完了メッセージを表示

重要: セルを操作するときは必ず 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 各シートで実行したい処理 ヘッダー挿入+書式設定(デモ用)

コードの流れ

  1. スキップ対象の定義: Array("目次", "集計", "マスタ") でスキップするシート名を配列で指定
  2. 非表示チェック: ws.Visible <> xlSheetVisible なら処理をスキップ
  3. シート名チェック: IsInArray 関数でスキップ対象に含まれるか確認
  4. 処理の実行: 対象シートにヘッダー挿入+書式設定
  5. 完了メッセージ: 処理したシート数を表示

全シートにヘッダーを挿入した後、ボタン(/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最終行・最終列の取得。シートごとにデータ範囲が異なるときに正確に処理範囲を取得したい場合に

コメント

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