For Eachって何ですか?(ちょっと難しいかもねって話)


VBAには繰り返しの命令(ステートメント)が3つ(本当は4つ)あります。ひとつは回数による繰り返すのFor Nextステートメント。次に、条件による繰り返しのDo Loopステートメント。そして3つめがこのFor Eachステートメントです。これが分からないという方がとても多いです。なぜ分からないのか。その理由はさまざまですが、中でも「オブジェクト変数を使わなければならない」というのがネックになっているようです。今回の動画では、そのオブジェクト変数についても解説しています。ちなみに、4つめの繰り返し命令というのは、While Wendステートメントですが、使っている人はほとんどいませんし、そもそも知っている人が少ないです。While Wendは、Do Loopと同じ条件による繰り返しですが、Do Loopと同じことしかできず、さらに、Do Loopに比べてデメリットもあります。なので誰も使いませんし、知らなくていいやつです。

↓左上にあるをクリックすると、チャンネル登録できます。ぜひ、チャンネル登録をお願いします。あなたのチャンネル登録が、私のやる気を維持向上してくれます(笑)

【補足】

オブジェクト変数の解説、ちょっと分かりにくかったかもしれません。
6:26 で、セルをオブジェクト変数Cに入れていますが、
これは「セルA1とセルB2」という"2つのセル"を入れているのではありません。
まず「セルA1」ひとつだけを変数Cに入れると、変数Cを使ってセルA1を操作できますよと。
続いて、今度は変数Cに「セルB2」をひとつだけ入れると、同じ書き方(C.アドレスなど)で
「セルB2」を操作できるという意味です。

また、8:30 あたりで次の解説をしています。

Dim C As Range
Set C = Range("A1")

これは、オブジェクト変数を宣言するときは、オブジェクトの名前を型に指定する
ということがポイントです。ちなみに

セルを入れる → As Range
ワークシートを入れる → As Worksheet
ブックを入れる → As Workbook

などのように宣言します。今回はセルですから「As Range」です。
そして次の

Set C = Range("A1")

ですが、これは、オブジェクト変数を、For Each"ではない"ところで
単体で使用する場合の書き方です。変数CにセルA1を入れるときは、こう書きます。
その後、For Eachの解説では、この「Set」が出てきません。
本来、オブジェクト変数に何かを入れるときは、必ずSetをつけなければいけませんが、
For Eachは、それを内部でやってくれますので、For Each内でSetは書きません。
このへんも、多くの方が悩むポイントだと思います。

「For Eachの解説」には、その前に「オブジェクト変数の解説」が必要なので、
今回は2つのことを解説しましたが、オブジェクト変数に関しては、
今回の動画では触れていない、もう一つの使い方があります。それが実務でよく出てきます。
そのへんの話は、いずれ違う動画で解説するつもりです。

解説では「セルを1つずつ操作する」例を示していますが、最後の実例では
セル操作のコードをお見せしていません。
なので、下記リンクからダウンロードできるサンプルブックに、
「選択した複数のセルをひとつずつ操作する例」を書いておきます。
それを実行して、イメージしてください。

ちょっと、この動画に関しては悔いが残ります。
せっかく投稿したので、このまま残しておきますが、スッキリしなかった方、すみませんでした。

''すべてのシート操作(For Each)
Sub Macro1()
    Dim A As Worksheet
    For Each A In Sheets
        A.Tab.Color = RGB(0, 0, 255)
    Next A
End Sub

''すべてのシート操作(For Next)
Sub Macro2()
    Dim i As Long
    For i = 1 To Sheets.Count
        Sheets(i).Tab.Color = RGB(255, 0, 0)
    Next i
End Sub
''すべてのシェイプ(For Each)
Sub Macro3()
    Dim A As Shape, cnt As Long
    For Each A In ActiveSheet.Shapes
        cnt = cnt + 1
        A.Left = ActiveSheet.Shapes(1).Left
        A.TextFrame2.TextRange.Characters.Text = cnt
        A.Fill.ForeColor.RGB = RGB(255, 0, 0)
    Next A
End Sub

''すべてのシェイプ(For Next)
Sub Macro4()
    Dim i As Long, cnt As Long
    For i = 1 To ActiveSheet.Shapes.Count
        cnt = cnt + 1
        ActiveSheet.Shapes(i).Left = ActiveSheet.Shapes(1).Left
        ActiveSheet.Shapes(i).TextFrame2.TextRange.Characters.Text = cnt
        ActiveSheet.Shapes(i).Fill.ForeColor.RGB = RGB(255, 0, 0)
    Next i
End Sub

''すべてのシェイプ(For Next + With)
Sub Macro5()
    Dim i As Long, cnt As Long
    With ActiveSheet
        For i = 1 To .Shapes.Count
            cnt = cnt + 1
            .Shapes(i).Left = .Shapes(1).Left
            .Shapes(i).TextFrame2.TextRange.Characters.Text = cnt
            .Shapes(i).Fill.ForeColor.RGB = RGB(255, 0, 0)
        Next i
    End With
End Sub

''1つ変数を使えば、もう少し短くなるか
Sub Macro6()
    Dim i As Long, cnt As Long, N As Single
    N = ActiveSheet.Shapes(1).Left
    With ActiveSheet.Shapes(i)
        For i = 1 To .Shapes.Count
            cnt = cnt + 1
            .Left = N
            .TextFrame2.TextRange.Characters.Text = cnt
            .Fill.ForeColor.RGB = RGB(255, 0, 0)
        Next i
    End With
End Sub
''すべてのブック-すべてのシート(For Each)
Sub Macro6()
    Dim WB As Workbook, WS As Worksheet
    For Each WB In Workbooks
        For Each WS In WB.Sheets
            WS.PrintOut
        Next WS
    Next WB
End Sub

''すべてのブック-すべてのシート(For Next)
Sub Macro7()
    Dim i As Long, j As Long
    For i = 1 To Workbooks.Count
        For j = 1 To Workbooks(i).Sheets.Count
            Workbooks(i).Sheets(j).PrintOut
        Next j
    Next i
End Sub
''オブジェクト変数によるコードの短縮化
Sub Macro8()
    Dim i As Long
    For i = 1 To 100
        Workbooks("2020年度営業企画").Sheets("東京支店").Cells(i, 1).Copy Workbooks("2020年度営業企画").Sheets("東京支店").Cells(i, 2)
    Next i
End Sub

Sub Macro9()
    Dim i As Long, A As Worksheet
    Set A = Workbooks("2020年度営業企画").Sheets("東京支店")
    For i = 1 To 100
        A.Cells(i, 1).Copy A.Cells(i, 2)
    Next i
End Sub
''動画の「オブジェクト変数の解説」で、セルをひとつずつ操作を例にしましたが
''実際のコードでは示していなかったので、ここに追記します
''複数のセルを選択して、次のコードを試してください

Sub Macro1()
    ''選択したセルに、そのセルをアドレスを代入し、背景色を赤にします
    Dim C As Range
    For Each C In Selection
        C.Value = C.Address(False, False)
        C.Interior.Color = RGB(255, 0, 0)
    Next C
End Sub

Sub Macro2()
    ''選択したセルに、そのセルをアドレスを代入し、背景色を赤にします
    ''確認のため、1セル処理したところで画面を止めます
    Dim C As Range
    For Each C In Selection
        C.Value = C.Address(False, False)
        C.Interior.Color = RGB(255, 0, 0)
        MsgBox C.Address(False, False) & "を処理しました"
    Next C
End Sub

動画で使用したブックのダウンロード(20200722.xlsm)

Office TANAKAのYouTubeチャンネルはこちら(動画一覧ページ)