検証環境: 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
Cells・End・CurrentRegion・Resize など、ほかはすべて「対象セルを 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 の配管作業をやめて、結果を伝える
Range・Cells・End・Resize——数値の列を動かすだけなのに、配管作業が多すぎます。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"——シートで明示的に修飾しましょう。
