🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA Range の使い方 — セルの参照・読み書き(8つの例)

|

Excel VBA Range の使い方 — セルの参照・読み書き(8つの例)

検証環境: Excel 365 v2509 · Excel 2021 · Excel 2019 · 最終確認 2026-06-05

要点Range は1つまたは複数のセルを指すオブジェクトです。.Value で読み、同じく .Value で書きます。.Select は不要です。

Sub Rangeの基本()
    ' 1つのセルを「読む」
    Dim qty As Long
    qty = Range("B2").Value

    ' 1つのセルに「書く」
    Range("C2").Value = qty * 1.1

    ' まとめて1行を書く(ループ不要)
    Range("A1:C1").Value = Array("商品", "数量", "単価")
End Sub

CellsEndCurrentRegionResize など、ほかはすべて「対象セルを Range に渡す別の書き方」にすぎません。本記事では実務で本当に使う8つを紹介します。

例はすべて Sheet1 の小さな表を前提とします。見出し 商品 / 数量 / 単価A1:C1、データは2行目以降です。

Range オブジェクトとは何か

Range は Excel VBA で最もよく使うオブジェクトです。1つのセル、セルのブロック、行や列全体、さらには離れた複数ブロックまでを表します。値を読む、数式を書く、色を変える、コピーする、並べ替える——そのほとんどは Range に対して 呼び出す メソッドプロパティ です。

Range("A2").Value = "Widget"                ' 1つのセルのプロパティ
Range("A2:C2").Interior.Color = vbYellow    ' 3つのセルのプロパティ
Range("A:A").Columns.AutoFit                ' 列全体のプロパティ

例1 — Range と Cells(どちらを使うか)

どちらもセルを指します。違いは「アドレスの指定方法」です。

向いている用途 構文
Range("A2") 固定の読みやすいアドレス 名前ボックスと同じ文字列アドレス
Cells(2, 1) 数値から計算した位置 Cells(行, 列)行が先
' この2行は同じセル(2行目・1列目)を指します:
Range("A2").Value = "Widget"
Cells(2, 1).Value = "Widget"

アドレスが分かっているときは Range、行や列が変数になるループの中では Cells を使います。

Dim r As Long
For r = 2 To 6
    Cells(r, 3).Value = Cells(r, 2).Value * 1.1   ' 単価 = 数量 * 1.1
Next r

組み合わせも可能です。Range(Cells(2, 1), Cells(6, 3)) は2つの角セルからブロック A2:C6 を作ります。角を計算で求めるときに最適です。

例2 — .Value.Value2.Text.Formula

初心者が必ずはまる落とし穴です。同じセルが4つの異なる結果を返します。

' セル B2 は数式 =A2*5 により "¥1,250" と表示されている
Debug.Print Range("B2").Value     ' 1250    (通貨・日付を意識する Variant)
Debug.Print Range("B2").Value2    ' 1250    (生の Double — 最速)
Debug.Print Range("B2").Text      ' "¥1,250"  (利用者に「見えている」文字列)
Debug.Print Range("B2").Formula   ' "=A2*5"  (数式そのもの)

使い分けの目安:

  • .Value2 — 大きな範囲を読むときや計算するとき。通貨・日付変換を省くので速く、丸められた通貨値に驚かされることもありません。
  • .Text — ほぼ読み取り専用で、表示されている文字列を返します。注意:列幅が狭いと "####" が返ります。
  • .Formula — 結果ではなく数式を読み書きします。

例3 — .Select をやめる(アンチパターンその1)

マクロ記録は至るところに .Select を書きます。実用的なマクロは書きません。選択は遅く、画面がちらつき、対象シートが違うと壊れます。

' ❌ 記録スタイル — 壊れやすく遅い
Range("A2").Select
Selection.Value = "Widget"

' ✅ Range に直接操作する
Range("A2").Value = "Widget"

選択する代わりにシートを明示すれば、画面に何が表示されていてもコードは動きます。

ThisWorkbook.Worksheets("Sheet1").Range("A2").Value = "Widget"

例4 — 最終行を求める(定番のイディオム)

A2:A100 のようなベタ書きはデータが増えると壊れます。この1行が A 列の本当の最終行を見つけます。

Dim lastRow As Long
lastRow = Cells(Rows.Count, 1).End(xlUp).Row    ' 一番下から上へジャンプ
MsgBox "データは " & lastRow & " 行目で終わります"

End(xlUp)Ctrl + ↑ を押す動作を再現します。範囲をデータに合わせる最も確実な方法です。

例5 — CurrentRegion で動的範囲

CurrentRegion はセルを囲む連続ブロック全体を取得します。Ctrl + Shift + 方向キーで選択される範囲とまったく同じです。行数を数える必要はありません。

Dim data As Range
Set data = Range("A1").CurrentRegion         ' 見出しを含む表全体
MsgBox data.Rows.Count & " 行 × " & data.Columns.Count & " 列"

' 見出し行を除く — 1行下げて(Offset)1行短く(Resize):
Dim body As Range
Set body = data.Offset(1, 0).Resize(data.Rows.Count - 1)

Offset(行, 列) は範囲をずらし、Resize(行, 列) は大きさを変えます。組み合わせれば、見出しを切り離す・列を足す・ブロックを広げる——どれもベタ書きアドレスなしで実現できます。

例6 — 範囲を読みやすくループする

各セルを処理したいなら、For Each がインデックス計算より読みやすいです。

Dim cell As Range
For Each cell In Range("B2:B6")
    If cell.Value > 100 Then cell.Interior.Color = vbGreen
Next cell

例7 — 範囲を丸ごと配列に読み込む(高速な方法)

プロの秘訣はこれです。シートに何千回も触れるのは遅い。範囲全体を一度でメモリに読み込み、そこで処理し、最後に一度だけ書き戻します。1万行なら8秒と0.1秒の差になります。

Sub 高速範囲()
    Dim arr As Variant
    arr = Range("A2:C10000").Value2          ' 1回の読み込み -> 2次元配列(1始まり)

    Dim i As Long
    For i = 1 To UBound(arr, 1)
        arr(i, 3) = arr(i, 2) * 1.1          ' メモリ上で計算、セルには触れない
    Next i

    Range("A2:C10000").Value2 = arr          ' 1回の書き込み
End Sub

arr = 範囲.Value2 のテクニックは非常に重要なので、専用の記事を用意しました。

例8 — 不連続範囲と名前付き範囲

Range は離れた複数ブロック(Union)を持てますし、名前付き範囲はその名前で参照できます。

' 離れた2ブロックをまとめて着色:
Range("A2:A6, C2:C6").Interior.Color = vbCyan

' 名前ボックスで "TaxRate" と名付けた範囲:
Range("TaxRate").Value = 0.2

よくある Range のミス(と対処)

症状 原因 対処
違うシートが編集される シート未指定の Range(...)アクティブシートを使う ThisWorkbook.Worksheets("Sheet1").Range(...) を付ける
Cells(1, 2) が違うセルを指す Cells(行, 列) で、(列, 行) ではない 行番号が先
ループが激遅 セルを1つずつ読み書きしている 配列に読み込む(例7)
.Text"####" を返す 列幅が狭くて値を表示できない .Text ではなく .Value2 を読む
データ増加で範囲が足りない A2:A100 のベタ書き End(xlUp)CurrentRegion で動的に決める

Range の配管作業をやめて、結果を伝える

RangeCellsEndResize——数値の列を動かすだけなのに、配管作業が多すぎます。ExcelMaster Agent なら自然な日本語で伝えるだけ——「Sheet1 で、B 列の数量すべてに 1.1 を掛けて、その結果を C 列に、データのある行数だけ書いて」——最終行・見出し・アクティブシートの罠まで考慮した安全なコードを生成します。無料で試す →

関連記事

よくある質問

VBA の Range と Cells の違いは? どちらもセルを指します。Range("A2") は文字列アドレス、Cells(2, 1) は数値の (行, 列) 座標で、位置が変数になるループに最適です。Range(Cells(2,1), Cells(6,3)) は両者を組み合わせ、計算した角からブロックを作ります。

VBA で .Value と .Value2 はどちらを使う? 大きな範囲の読み込みや計算には .Value2 を使います。生の Double を返し、通貨・日付変換を省くので高速です。.Value は通貨や日付の型が明示的に必要なときだけで十分です。

行・列が変数の範囲を参照するには? Cells(行, 列) を変数で使うか、ブロックなら Range(Cells(r1, c1), Cells(r2, c2))。最終行は Cells(Rows.Count, 1).End(xlUp).Row で求めます。

サイズが分からない表全体を参照するには? Range("A1").CurrentRegion が連続ブロック全体を返します。見出し行を除くには .Offset(1, 0).Resize(.Rows.Count - 1) を使います。

なぜ VBA で .Select を避けるべき? .Select は遅く、画面がちらつき、正しいシートがアクティブであることに依存します。範囲に直接操作し——Range("A2").Value = "x"——シートで明示的に修飾しましょう。