【ExcelVBA】全シートを一括処理!条件分岐で特定のシートだけ操作する方法|スパとふゆの0からはじめるExcelマクロ(4日目)

1. はじめに
Excelマクロ初心者の「ふゆさん」が、講師の「和風スパゲティさん」と一緒にVBAをゼロから学んでいくライブ配信イベント「スパとふゆの0からはじめるExcelマクロ」。この記事は、その4日目の学習内容をまとめたものです。

今回のテーマは、実務で非常に重要な「複数のシートを扱う処理」と「条件分岐」です。月別の売上シートや支店ごとのデータシートなど、同じ形式のシートが複数ある場合に、それらを一括で処理する方法を学びます。
この記事で達成できること

この記事を読み終える頃には、以下のスキルが身についているはずです。
- ブック内の全シートに同じ処理をする方法
- 「特定の名前のシート」や「表示されているシート」だけを処理する方法
- コードを見やすく整理するテクニック
2. ステップ1:すべてのシートに同じ処理をする(For…Next)
まずは基本として、ブック内のすべてのシートに対して同じ処理を繰り返す方法を学びます。
基本的な考え方
Excelのシートは、Worksheets("シート名")のように名前で指定するだけでなく、Worksheets(1)やWorksheets(2)のように左からの順番(インデックス番号)でも管理できます。この番号を利用して、シートを1枚目から順番に処理していきます。
二重ループ構造

複数のシートにあるデータを一行ずつ処理する場合、以下のような「二重ループ」の構造を使います。
- 外側のループ: シートを1枚目から最後のシートまで順番に切り替えるループ。
- 内側のループ: 選択されたシート内のデータを2行目から最終行まで処理するループ。
この構造により、VBAはまず外側のループで1枚目のシートを選択し、次に内側のループを最後まで実行してそのシートの全行を処理します。それが終わってから初めて、外側のループが2枚目のシートに進み、再び内側のループで全行を処理する…という流れを、最後のシートまで自動で繰り返してくれるのです。
動的なシート数への対応

シートの枚数をFor シート番号 = 1 To 3のように固定で書いてしまうと、シートが増えたり減ったりするたびにコードを修正する必要があり、非常に不便です。
そこで、ThisWorkbook.Worksheets.Countというコードを使います。これは「このマクロが書かれているブック(ThisWorkbook)のシート(Worksheets)の数(Count)」を自動で取得してくれるため、シートの増減に柔軟に対応できるマクロになります。
コード例
以下は、ブック内の全シートを対象に、6列目の商品コードをもとに「商品マスタ」シートから品物名をWorksheetFunction.XLookupで取得し、7列目に転記するコードです。
Sub 全シートの品物名を取得する_シート数をカウントVer()
Dim シート番号 As Long
For シート番号 = 1 To ThisWorkbook.Worksheets.Count
Dim 行 As Long
Dim 最終行 As Long
最終行 = Worksheets(シート番号).UsedRange.Rows.Count
For 行 = 2 To 最終行
'商品名をマスタからXLookupで取得
'「 _」で改行ができる
Worksheets(シート番号).Cells(行, 7) = WorksheetFunction.XLookup _
(Worksheets(シート番号).Cells(行, 6), _
Worksheets("商品マスタ").Columns("A"), _
Worksheets("商品マスタ").Columns("B"))
Next
Next
End Sub3. ステップ2:特定のシートだけ処理する(If…Then)

全シートをループ処理する方法は便利ですが、実務では「商品マスタ」シートや集計用のシートなど、処理の対象外としたいシートが含まれていることがほとんどです。
このような場合に、特定の条件に合致するシートだけを処理するのがIf...Thenステートメント(条件分岐)です。

3-1. シート名で判定する(Left関数)
「データ_東京」「データ_大阪」のように、特定の文字列で始まる名前のシートだけを処理したいケースです。シート名を取得する.Nameプロパティと、文字列の左から指定した文字数を抽出するLeft関数を組み合わせます。
手法の解説 If Left(Worksheets(シート番号).Name, 3) = "データ" Then このコードは、「シート名の左から3文字が『データ』であれば」という条件を表します。
コード例
Sub 全シートの品物名を取得する_シート名をIFで判定Ver()
Dim シート番号 As Long
For シート番号 = 1 To ThisWorkbook.Worksheets.Count
Dim 行 As Long
Dim 最終行 As Long
最終行 = Worksheets(シート番号).UsedRange.Rows.Count
If Left(Worksheets(シート番号).Name, 3) = "データ" Then
For 行 = 2 To 最終行
'商品名をマスタからXLookupで取得
'「 _」で改行ができる
Worksheets(シート番号).Cells(行, 7) = WorksheetFunction.XLookup _
(Worksheets(シート番号).Cells(行, 6), _
Worksheets("商品マスタ").Columns("A"), _
Worksheets("商品マスタ").Columns("B"))
Next
End If
Next
End Sub3-2. 非表示のシートは除外する(Visibleプロパティ)
計算の途中経過などを保存しておく作業用の非表示シートは、一括処理の対象から除外したい場合が多くあります。シートが表示されているかどうかは.Visibleプロパティで判定できます。
手法の解説 If Worksheets(シート番号).Visible = True Then このコードは、「シートの表示状態(Visible)がTrue(真)であれば」という条件です。これにより、表示されているシートのみを処理対象にできます。
コード例 以下のコードでは、まずシートが表示されているかを判定し、次にシート名が「データ」で始まるかを判定する、If文が二重(ネスト)の構造になっています。
Sub 全シートの品物名を取得する_表示シートかつシート名をIFで判定Ver()
Dim シート番号 As Long
For シート番号 = 1 To ThisWorkbook.Worksheets.Count
Dim 行 As Long
Dim 最終行 As Long
最終行 = Worksheets(シート番号).UsedRange.Rows.Count
If Worksheets(シート番号).Visible = True Then
If Left(Worksheets(シート番号).Name, 3) = "データ" Then
For 行 = 2 To 最終行
'商品名をマスタからXLookupで取得
'「 _」で改行ができる
Worksheets(シート番号).Cells(行, 7) = WorksheetFunction.XLookup _
(Worksheets(シート番号).Cells(行, 6), _
Worksheets("商品マスタ").Columns("A"), _
Worksheets("商品マスタ").Columns("B"))
Next
End If
End If
Next
End Sub
3-3. 複数の条件をまとめる(And / Or)
「表示されていて」かつ「名前がデータで始まる」のように複数の条件を組み合わせたい場合、And演算子を使うとIf文のネストを解消し、コードをスッキリさせることができます。
手法の解説 If 条件A And 条件B Then このように記述すると、「条件Aと条件Bの両方を満たす場合」にのみ処理を実行できます。ちなみに、Orを使うと「条件Aまたは条件Bのどちらかを満たす場合」という条件になります。
コード例 先ほどのネストしたIf文をAndで一つにまとめました。処理内容は同じですが、コードがシンプルで読みやすくなっています。
Sub 全シートの品物名を取得する_表示シートかつシート名をIFで判定1行にまとめるVer()
Dim シート番号 As Long
For シート番号 = 1 To ThisWorkbook.Worksheets.Count
Dim 行 As Long
Dim 最終行 As Long
最終行 = Worksheets(シート番号).UsedRange.Rows.Count
If Worksheets(シート番号).Visible = True And Left(Worksheets(シート番号).Name, 3) = "データ" Then
For 行 = 2 To 最終行
'商品名をマスタからXLookupで取得
'「 _」で改行ができる
Worksheets(シート番号).Cells(行, 7) = WorksheetFunction.XLookup _
(Worksheets(シート番号).Cells(行, 6), _
Worksheets("商品マスタ").Columns("A"), _
Worksheets("商品マスタ").Columns("B"))
Next
End If
Next
End Sub
4. ステップ3:コードを見やすく整理する(Setステートメント)

課題
Worksheets(シート番号).Cells(行, 7)のように、シートを指定する記述は長くなりがちです。先ほどのコードでも、この長い記述が何度も登場し、コードが冗長で読みにくくなっています。
解決策:シートオブジェクトを変数に格納する
この課題を解決するのがSetステートメントです。 Set 処理シート = Worksheets(シート番号) このように書くことで、Worksheets(シート番号)というシートオブジェクトそのものを「処理シート」という名前の変数に格納できます。
ここで一つ注意点があります。行番号のような単なる数値を変数に入れるときは行 = 2のように書きますが、ワークシートやセルといった「オブジェクト(モノ)」を変数に格納するときは、Setというキーワードを先頭につける、というVBAの「お作法」があります。これは「大きめのものを変数に入れるときのおまじない」と覚えておくと良いでしょう。
メリット
この手法には2つの大きなメリットがあります。
- コードの可読性向上:
処理シート.Cells(行, 7)のように、コードが短く、何をしているかが直感的に分かりやすくなります。 - 入力候補機能(インテリセンス)の活用:
Worksheets(シート番号)のような書き方では、VBE(コードを書く画面)が具体的にどのオブジェクトを指しているか判断できないため、.(ドット)を打ってもプロパティやメソッドの候補が表示されません。しかし、Dim 処理シート As Worksheetと型を明示して変数にSetすると、VBEが「これはワークシートだ」と認識してくれるため、.Visibleや.Nameといった候補が表示されるようになります。これにより、スペルミスを防ぎ、コーディングの効率が格段に向上します。
コード例
これまでに学んだテクニック(.Count, And, Set)をすべて盛り込み、冗長な記述をスッキリさせた最終形のコードです。
Sub 全シートの品物名を取得する_複数条件をANDでやるVer()
Dim シート番号 As Long
For シート番号 = 1 To ThisWorkbook.Worksheets.Count
Dim 処理シート As Worksheet
Set 処理シート = Worksheets(シート番号)
Dim 行 As Long
Dim 最終行 As Long
最終行 = 処理シート.UsedRange.Rows.Count
If 処理シート.Visible = True _
And Left(処理シート.Name, 3) = "データ" Then
For 行 = 2 To 最終行
'商品名をマスタからXLookupで取得
'「 _」で改行ができる
処理シート.Cells(行, 7) = WorksheetFunction.XLookup _
(処理シート.Cells(行, 6), _
Worksheets("商品マスタ").Columns("A"), _
Worksheets("商品マスタ").Columns("B"))
Next
End If
Next
End Sub5. 初心者あるある!「End Ifに対応するIfブロックがありません」エラー

エラーの紹介

VBA初心者がIf文やForループを使い始めると、よく遭遇するのが以下のエラーです。
コンパイル エラー: End Ifに対応する If ブロックがありません。
これは、Ifの始まりとEnd Ifの終わりの数が合っていない場合に発生します。Ifを書いたのに対応するEnd Ifを書き忘れたり、逆にEnd Ifが多すぎたり、For...NextのループとIf...End Ifのブロックが正しく入れ子になっていなかったりすると、VBAがコードの構造を正しく解釈できずにエラーとなります。
対処法
このエラーを防ぐための、効果的な習慣があります。
Ifを書いたら、すぐにEnd Ifを書く:If 条件 Thenと書いたら、その直後に下の行にEnd Ifを記述する癖をつけましょう。その後で、IfとEnd Ifの間に処理内容を書き足していくことで、対応関係が崩れるのを防げます。ForとNextも同様です。- インデント(字下げ)を徹底する:
IfブロックやForループの中の処理は、Tabキーを使って一段右にずらす(インデントする)ことを徹底しましょう。インデントを整えることで、どのIfがどのEnd Ifに対応しているのかが視覚的に一目瞭然となり、エラーの発見が容易になります。 - エラー表示を鵜呑みにしない: このエラーが発生すると、VBEがコードの一部を黄色くハイライトして場所を教えてくれようとします。しかし、VBEは
IfとEnd Ifの対応関係を正確に理解しているわけではないため、まったく見当違いの場所を指し示すことがよくあります。ハイライトされた場所を blindly信じるのではなく、「どこかでIf/End IfかFor/Nextのペアが崩れているんだな」と考え、インデントを手がかりにコード全体の構造を見直すようにしましょう。
6. まとめ・アーカイブ動画

この記事では、複数のシートを効率的に扱うためのVBAテクニックを学びました。
- For…Nextループ:
ThisWorkbook.Worksheets.Countを使って、すべてのシートを順番に処理する。 - If…Thenによる条件分岐:
.Nameや.Visibleプロパティを使って、特定のシートだけを処理対象にする。And演算子で複数の条件を組み合わせる。 - Setステートメント: シートオブジェクトを変数に入れ、コードを読みやすく、書きやすくする。
これらのテクニックを組み合わせることで、手作業では時間がかかる定型業務を劇的に効率化できます。
関係者の紹介
講師:和風スパゲティさん
X(旧Twitter): @wafu_spaghetti
生徒:ふゆさん
X(旧Twitter): @id_mimipr
運営コミュニティ:Excel-Fun.xls*
公式サイト: https://sites.google.com/view/excel-vba-fun-for-event 公式X(旧Twitter): @ExcelFunFun
アーカイブ動画
今回のライブ配信の全編は、以下のYouTube再生リストからご覧いただけます。動画で実際の操作を見ながら復習したい方はこちらからどうぞ!
