Excel VBA 逆引き集 | 範囲の選択回避(Selectを使わない)

Excel VBA
スポンサーリンク

範囲の選択回避(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 を正しく使うと安全に可変範囲を扱える。
タイトルとURLをコピーしました