範囲の選択回避(Selectを使わない)
画面操作に依存せず、直接セルや範囲を指定して処理すれば、コードは短く速く、壊れにくくなります。Select/Activate を省くことで大幅な高速化と可読性向上が期待できます。
基本原則:直接参照で書く
Sub NoSelect_Basics()
'A1に値を入れる(選択不要)
Range("A1").Value = "Hello"
'B2:D5を一括で塗る
Range("B2:D5").Interior.Color = RGB(255, 235, 156)
'列と行を直接参照
Columns("E").ColumnWidth = 18
Rows(2).RowHeight = 28
End Sub
VB- ポイント:
- 直接参照: Range/Cells/Columns/Rows に対して操作する。ActiveCellに頼らない。
- Withの活用: 同じ対象に複数設定をまとめると読みやすい。
- メリット: 高速・安定・短いコード。
典型置き換え:Select/Activate をやめる
Sub Bad_SelectPattern()
Range("A1").Select
Selection.Value = "NG"
End Sub
Sub Good_DirectPattern()
Range("A1").Value = "OK"
End Sub
VB- ポイント:
- Selection依存の排除: 画面選択に左右されないコードへ。
- 結果同じなら短く: 直接プロパティに代入するほうが速い。
例1:コピー&貼り付け(クリップボードなしで高速)
Sub CopyValues_NoClipboard()
Dim src As Range, dst As Range
Set src = Range("B2:D100")
Set dst = Range("F2").Resize(src.Rows.Count, src.Columns.Count)
dst.Value = src.Value '値だけ転記(高速・安定)
End Sub
VB- ポイント:
- Resizeで貼り先を一致: 行数・列数を合わせる。
- 値だけなら最速: クリップボード不要で安定動作。
例2:最終行まで動的に処理(直接参照+可変範囲)
Sub FormatToLastRow()
Dim last As Long, rng As Range
last = Cells(Rows.Count, "B").End(xlUp).Row
Set rng = Range("B2:D" & last)
With rng
.Font.Name = "Meiryo"
.NumberFormat = "#,##0"
.Columns.AutoFit
End With
End Sub
VB- ポイント:
- 可変範囲: last行を計算して Range を組み立てる。
- Withでまとめる: 重複参照を減らして読みやすく。
例3:CurrentRegion/SpecialCells を使って「見えているところ」だけ
Sub OperateOnCurrentRegion()
With Range("B2").CurrentRegion
.Rows(1).Font.Bold = True
.Columns.AutoFit
End With
End Sub
Sub OperateOnVisibleOnly()
Dim vis As Range
Set vis = Range("B2:E200").SpecialCells(xlCellTypeVisible)
vis.Interior.Color = RGB(242, 242, 242)
End Sub
VB- ポイント:
- CurrentRegion: 連続データ領域を自動取得して直接操作。
- SpecialCells: フィルタ後の可視セルだけ対象にできる。
例4:Findで検索して直接書き込む(Activate不要)
Sub FindAndFill()
Dim c As Range
Set c = Columns("A").Find(What:="合計", LookIn:=xlValues, LookAt:=xlWhole)
If Not c Is Nothing Then
c.Offset(0, 1).Value = "合計行です"
c.EntireRow.Font.Bold = True
End If
End Sub
VB- ポイント:
- FindはRangeを返す: 見つかったセルを直接操作。
- Offset/EntireRow: 相対移動・行全体も直接参照。
例5:配列でループを減らす(高速まとめ処理)
Sub BulkProcess_ByArray()
Dim data As Variant, i As Long
data = Range("B2:B500").Value '2次元配列で取得
For i = 1 To UBound(data, 1)
If data(i, 1) < 0 Then data(i, 1) = 0 'メモリ上で変換
Next i
Range("B2:B500").Value = data '一括で書き戻し
End Sub
VB- ポイント:
- 一括取得・一括書き戻し: セル往復を最小化して高速化。
例6:別シート・別ブックでも“直接修飾”で確実に
Sub CrossSheet_Direct()
Worksheets("Source").Range("B2:D20").Copy _
Destination:=Worksheets("Report").Range("A1")
End Sub
Sub CrossBook_Direct()
Dim wb As Workbook
Set wb = Workbooks.Open("C:\Data\Report.xlsx")
ThisWorkbook.Worksheets("Src").Range("B2:D20").Value = _
wb.Worksheets("Tgt").Range("A2:C20").Value
wb.Close SaveChanges:=True
End Sub
VB- ポイント:
- 修飾を明示: ブック・シート名を付けて誤対象を防ぐ。
置き換えテンプレート集(よくあるSelectパターン)
'NG: Selectしてから入力
Range("C3").Select
Selection.Value = 1
'OK: 直接代入
Range("C3").Value = 1
'NG: Selectしてからコピー・ペースト
Range("B2:D5").Select
Selection.Copy
Range("F2").Select
ActiveSheet.Paste
'OK: 直接Copy Destination
Range("B2:D5").Copy Destination:=Range("F2")
'NG: Activateで移動
Sheets("Report").Activate
Range("A1").Select
Selection.Font.Bold = True
'OK: 修飾して直接
Worksheets("Report").Range("A1").Font.Bold = True
VB- ポイント:
- 選択の意味がない処理はすべて直接参照へ。
実務の落とし穴と対策
- Selection依存のバグ: 画面選択がズレると誤処理。常に対象を直接参照する。
- 速度低下: Select/Activate は画面更新を伴い遅い。不要なら省略、配列・With・一括操作で高速化。
- 参照の曖昧さ: どのブック・シートか不明なコードは危険。ThisWorkbook/Worksheets を明示。
- 範囲の組み立てミス: CurrentRegion、Resize、Offset を正しく使うと安全に可変範囲を扱える。

