20250815_【VBA】スパとふゆの0からはじめるExcelマクロ(4日目)

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

1. はじめに

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

あわせて読みたい
20250801_【VBA】スパとふゆの0からはじめるExcelマクロ(3日目) https://www.youtube.com/watch?v=SuM_wPNzgfM&list=PLF7umZQFDaaDtrOPIlNx8tPVAgWEe1A5i&index=3 祝・VBAプログラマー(見習い)爆誕!「スパとふゆの0からは...

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

この記事で達成できること

この記事を読み終える頃には、以下のスキルが身についているはずです。

  • ブック内の全シートに同じ処理をする方法
  • 「特定の名前のシート」や「表示されているシート」だけを処理する方法
  • コードを見やすく整理するテクニック

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 Sub

3. ステップ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 Sub

3-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つの大きなメリットがあります。

  1. コードの可読性向上: 処理シート.Cells(行, 7)のように、コードが短く、何をしているかが直感的に分かりやすくなります。
  2. 入力候補機能(インテリセンス)の活用: 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 Sub

5. 初心者あるある!「End Ifに対応するIfブロックがありません」エラー

エラーの紹介

VBA初心者がIf文やForループを使い始めると、よく遭遇するのが以下のエラーです。

コンパイル エラー: End Ifに対応する If ブロックがありません。

これは、Ifの始まりとEnd Ifの終わりの数が合っていない場合に発生します。Ifを書いたのに対応するEnd Ifを書き忘れたり、逆にEnd Ifが多すぎたり、For...NextのループとIf...End Ifのブロックが正しく入れ子になっていなかったりすると、VBAがコードの構造を正しく解釈できずにエラーとなります。

対処法

このエラーを防ぐための、効果的な習慣があります。

  1. Ifを書いたら、すぐにEnd Ifを書く: If 条件 Thenと書いたら、その直後に下の行にEnd Ifを記述する癖をつけましょう。その後で、IfEnd Ifの間に処理内容を書き足していくことで、対応関係が崩れるのを防げます。ForNextも同様です。
  2. インデント(字下げ)を徹底する: IfブロックやForループの中の処理は、Tabキーを使って一段右にずらす(インデントする)ことを徹底しましょう。インデントを整えることで、どのIfがどのEnd Ifに対応しているのかが視覚的に一目瞭然となり、エラーの発見が容易になります。
  3. エラー表示を鵜呑みにしない: このエラーが発生すると、VBEがコードの一部を黄色くハイライトして場所を教えてくれようとします。しかし、VBEはIfEnd Ifの対応関係を正確に理解しているわけではないため、まったく見当違いの場所を指し示すことがよくあります。ハイライトされた場所を blindly信じるのではなく、「どこかでIf/End IfFor/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再生リストからご覧いただけます。動画で実際の操作を見ながら復習したい方はこちらからどうぞ!

【VBA】スパとふゆの0からはじめるExcelマクロ 再生リスト

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次