行列ループ(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
VB2) 条件付き塗り分け(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
VB3) 最初の一致を見つけたら終了(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
VB4) 二重ループの「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 で統一すると保守しやすい。
