Excel VBA 逆引き集 | 行列ループ(2重)

Excel VBA
スポンサーリンク

行列ループ(2重)

「行×列」の格子状データを処理する定番が二重ループです。For…Next の入れ子が基本ですが、For Each で Rows/Columns を回す方法、配列でまとめて処理して高速化する方法も押さえておくと実務で強いです。


基本パターン

'最も基本的な二重For…Next(外側=行、内側=列)
Sub DoubleLoop_Basic()
    Dim r As Long, c As Long
    For r = 2 To 20
        For c = 2 To 6
            Cells(r, c).Value = r & "," & c
        Next c
    Next r
End Sub
VB
'二重For Each(行の集合を回して各行の列を回す)
Sub DoubleLoop_ForEach()
    Dim rw As Range, cell As Range
    For Each rw In Range("B2:F20").Rows
        For Each cell In rw.Cells
            cell.Value = cell.Value & "✓"
        Next cell
    Next rw
End Sub
VB
  • 外側は行・内側は列: 読みやすく、意図が明瞭。
  • 範囲は明示指定: 余計なセルに触らないための基本。
  • Select/Activate不要: 直接 Cells/Range を操作する。

実務テンプレート

1) 行×列の計算(数量×単価→結果列へ)

'1) 行×列の計算(数量×単価→結果列へ)
Sub Calc_Grid()
    Dim r As Long, c As Long
    For r = 2 To 100
        For c = 2 To 5
            '例:各セルに行番号×列番号を入れる
            Cells(r, c).Value = r * c
        Next c
    Next r
End Sub
VB

2) 条件付き塗り分け(80以上は緑、その他は赤)

'2) 条件付き塗り分け(80以上は緑、その他は赤)
Sub Color_ByThreshold()
    Dim r As Long, c As Long, v
    For r = 2 To 100
        For c = 2 To 6
            v = Cells(r, c).Value
            If v <> "" Then
                If v >= 80 Then
                    Cells(r, c).Interior.Color = RGB(198, 239, 206)
                Else
                    Cells(r, c).Interior.Color = RGB(255, 199, 206)
                End If
            End If
        Next c
    Next r
End Sub
VB

3) 最初の一致を見つけたら終了(Exit Forの使い方)

'3) 最初の一致を見つけたら終了(Exit Forの使い方)
Sub Find_FirstMatch_Exit()
    Dim r As Long, c As Long
    For r = 2 To 100
        For c = 2 To 6
            If Cells(r, c).Value = "東京" Then
                Cells(r, c).Font.Bold = True
                Exit For  '内側の列ループを抜ける
            End If
        Next c
        '外側まで抜けたいならフラグを使う
        If Cells(r, c).Font.Bold = True Then Exit Sub
    Next r
End Sub
VB

4) 二重ループの「Continue」相当(このセルだけスキップ)

'4) 二重ループの「Continue」相当(このセルだけスキップ)
Sub Skip_ThisCell()
    Dim r As Long, c As Long
    For r = 2 To 50
        For c = 2 To 6
            If Cells(r, c).Value = "" Then GoTo NextCell
            Cells(r, c).Value = "処理済"
NextCell:
        Next c
    Next r
End Sub
VB
  • 最初の一致だけ: Exit For を使う。外側も抜けるならフラグや Exit Sub と併用。
  • スキップ: GoToでラベルへ飛ばすか、Ifで処理ブロックを囲う。

可視セル・部分範囲への適用

'フィルタ後の可視セルを行列ループで安全に処理
Sub DoubleLoop_VisibleOnly()
    Dim area As Range, visRows As Range, rw As Range, cell As Range
    Set area = Range("A1").CurrentRegion
    area.AutoFilter Field:=2, Criteria1:="=営業A"

    On Error Resume Next
    Set visRows = area.Offset(1).Resize(area.Rows.Count - 1).SpecialCells(xlCellTypeVisible).Rows
    On Error GoTo 0

    If Not visRows Is Nothing Then
        For Each rw In visRows
            For Each cell In rw.Columns("C").Resize(, 3).Cells 'C:Eの3列だけ
                cell.Value = "対象"
            Next cell
        Next rw
    End If
End Sub
VB
  • 可視セルだけ: SpecialCells(xlCellTypeVisible) を先に使い、行の集合で回すと重複処理を防げる。
  • 列を絞る: 必要な列だけ Resize で限定する。

高速化:配列でまとめて処理

'配列に読み込み→二重ループで計算→一括で書き戻し(最速の定番)
Sub DoubleLoop_ArrayFast()
    Dim rg As Range, data As Variant
    Set rg = Range("C2:F1000")

    data = rg.Value '2次元配列へ

    Dim r As Long, c As Long
    For r = 1 To UBound(data, 1)
        For c = 1 To UBound(data, 2)
            If IsNumeric(data(r, c)) Then
                data(r, c) = data(r, c) * 1.1 '例:10%上乗せ
            End If
        Next c
    Next r

    rg.Value = data '一括書き戻し
End Sub
VB
'画面更新・再計算オフのラップ(大量処理の定型)
Sub SpeedWrap()
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual

    '…二重ループの本処理…

    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
End Sub
VB
  • 配列処理: セルに何度もアクセスせず、まとめて値を扱うので桁違いに速い。
  • ScreenUpdating/Calculation: 大量データで体感速度が大幅に上がる。

例題で練習

'例題1:A2:C11 に「行番号×列番号」を入れる
Sub Example_FillRCProduct()
    Dim r As Long, c As Long
    For r = 2 To 11
        For c = 1 To 3
            Cells(r, c).Value = (r - 1) * c
        Next c
    Next r
End Sub

'例題2:B2:E20 のうち空白はスキップして「✓」を付ける
Sub Example_SkipBlanksMark()
    Dim r As Long, c As Long
    For r = 2 To 20
        For c = 2 To 5
            If Trim(Cells(r, c).Value) = "" Then GoTo NextCell
            Cells(r, c).Value = Cells(r, c).Value & "✓"
NextCell:
        Next c
    Next r
End Sub

'例題3:選択範囲の数式だけ値化(二重For Each)
Sub Example_Selection_FormulasToValues()
    If TypeName(Selection) = "Range" Then
        Dim rw As Range, cell As Range
        For Each rw In Selection.Rows
            For Each cell In rw.Cells
                If cell.HasFormula Then cell.Value = cell.Value
            Next cell
        Next rw
    End If
End Sub
VB

実務の落とし穴と対策

  • 重複処理: 可視セルを「範囲全体」で回すと同じ行を列数分処理しがち。行集合→必要列に絞って回す。
  • 無限/過剰アクセス: ループ境界は明示し、余計なセルに触れない。Cells(r, c) の r,c は必ず範囲内。
  • 数式の破壊: 値書き込みで数式が消える。値化が目的か表示だけ変更かを明確に。
  • 速度: セル直アクセスの二重ループは遅い。配列でまとめる、一括代入・書式変更を優先する。
  • 可読性: 外=行、内=列、変数名は r/c や row/col で統一すると保守しやすい。
タイトルとURLをコピーしました