【VBA】Rangeの使い方|セルの指定・範囲操作を基本から解説

スポンサーリンク

VBAでセルを操作するとき「Range("A1")」は書けるけれど、動的な範囲指定になると急に手が止まる。そんな経験はありませんか?

固定のセル番地しか使えないままだと、行数が変わるたびにコードを書き直すことになります。データが増えるほど手間も増える悪循環です。

この記事では、Rangeの基本から Offset・Resize・CurrentRegion といった動的操作まで体系的に解説します。コピペで使えるサンプルコード付きなので、すぐに実務に活かせますよ。

NOTE

VBEの起動方法や画面の見方は「VBE画面の見方」で解説しています。初めてマクロを書く方は先にチェックしてみてください。

VBA Rangeプロパティとは?

Rangeは、ワークシート上のセルやセル範囲を指定するためのプロパティです。

指定したセルに対して値の読み書き・書式変更・コピー・削除ができます。VBAでExcelを動かすなら、ほぼ必ず使う基本中の基本です。

NOTE

Cellsプロパティでもセルを指定できます。どちらも取得するのは「Rangeオブジェクト」です。Rangeは文字列指定、Cellsは数値指定という違いがあります。

Rangeの基本構文

'--- 単一セルを指定 ---
Range("A1")

'--- セル範囲を指定 ---
Range("A1:C10")

'--- シートを明示して指定 ---
ActiveSheet.Range("A1")
Worksheets("Sheet1").Range("A1")

ActiveSheet.Range("A1")ActiveSheet は省略できます。ただし省略すると、別シートを操作するマクロで意図しないシートを参照することがあります。慣れないうちはシートを明示しましょう。

VBA Rangeの基本的な使い方

ここからは、Rangeのセル指定パターンを1つずつ見ていきましょう。

単一セルを指定する

1つのセルを指定するには、ダブルクォーテーションの中にセル番地を書きます。

Sub SingleCell()
    '--- A1セルに値を入力 ---
    Range("A1").Value = "こんにちは"
End Sub

.Value は省略しても動きます。ただし明示した方がコードの意図が伝わりやすいです。

セル範囲を指定する

複数のセルをまとめて指定するには、コロン : で範囲を表します。

Sub CellRange()
    '--- A1からD8までの範囲を選択 ---
    Range("A1:D8").Select
End Sub

シート上でドラッグして選ぶ感覚と同じです。

飛び飛びのセルを指定する

離れた複数のセルを指定するには、カンマ , で区切ります。

Sub NonContiguous()
    '--- 飛び飛びのセルを太字にする ---
    Range("A1,C3,E5").Font.Bold = True
End Sub

Excelで Ctrl を押しながらクリックして複数選択するのと同じイメージです。

列全体・行全体を指定する

列や行をまるごと指定するには、列文字または行番号をコロンでつなぎます。

Sub EntireColumnAndRow()
    '--- A列全体を選択 ---
    Range("A:A").Select

    '--- A列からF列までを選択 ---
    Range("A:F").Select

    '--- 1行目全体を選択 ---
    Range("1:1").Select

    '--- 1行目から8行目までを選択 ---
    Range("1:8").Select
End Sub

名前定義されたセルを指定する

Excelの「名前の定義」で名前を付けたセル範囲は、Rangeから直接参照できます。

Sub NamedRange()
    '--- 名前定義「売上合計」を参照 ---
    Dim total As Double '合計金額
    total = Range("売上合計").Value

    MsgBox "合計: " & total
End Sub

名前定義を使うとセル位置が変わってもコード修正が不要です。実務では積極的に活用したいテクニックですね。

Offsetで隣接セルを参照する

基準セルから相対的にずらした位置を参照するのが Offset プロパティです。「A1から2行下・1列右」のような指定ができます。

Offsetの構文と動作イメージ

Range("基準セル").Offset(行方向, 列方向)
引数説明既定値
RowOffset行方向のずらし幅(正=下、負=上)0
ColumnOffset列方向のずらし幅(正=右、負=左)0

具体例を見てみましょう。

Sub OffsetDemo()
    '--- A1から2行下・1列右 → B3 ---
    Range("A1").Offset(2, 1).Value = "ここはB3"

    '--- C5から1行上 → C4 ---
    Range("C5").Offset(-1, 0).Value = "ここはC4"

    '--- A1から3列右(行方向は省略) → D1 ---
    Range("A1").Offset(, 3).Value = "ここはD1"
End Sub

片方の引数だけ指定すれば、もう一方は0として扱われます。行方向だけ、列方向だけのずらしも簡単です。

Offsetの実務活用例

入力データの隣のセルに処理結果を書き込むパターンです。

Sub WriteResult()
    Dim lastRow As Long '最終行
    Dim i As Long       'ループカウンター

    lastRow = Cells(Rows.Count, 1).End(xlUp).Row

    For i = 2 To lastRow
        '--- A列の値を2倍にしてB列に書き込む ---
        Cells(i, 1).Offset(0, 1).Value = Cells(i, 1).Value * 2
    Next i
End Sub

Offsetを使えば「今見ているセルの隣」を直感的に参照できます。For文と組み合わせると、行ごとの処理がスッキリ書けますよ。

Resize・CurrentRegionで範囲を動的に操作する

Offsetが「位置をずらす」操作なら、Resizeは「範囲の大きさを変える」操作です。CurrentRegionは表全体を自動取得してくれます。

Resizeの構文と動作イメージ

Range("基準セル").Resize(行数, 列数)
引数説明省略時
RowSize変更後の行数元の行数を維持
ColumnSize変更後の列数元の列数を維持
Sub ResizeDemo()
    '--- A1を起点に5行3列の範囲を選択 ---
    Range("A1").Resize(5, 3).Select

    '--- A1:C1(1行3列)を5行に広げる ---
    Range("A1:C1").Resize(5).Select
End Sub

Resizeは起点(左上セル)を変えずにサイズだけ変更します。Offsetとは役割が違うので、セットで覚えておきましょう。

CurrentRegionで表全体を取得する

CurrentRegionは、指定したセルを含む「空白行・空白列で囲まれた範囲」を自動取得するプロパティです。

Sub CurrentRegionDemo()
    Dim tbl As Range 'テーブル全体

    Set tbl = Range("A1").CurrentRegion

    MsgBox "表の範囲: " & tbl.Address & vbCrLf & _
           "行数: " & tbl.Rows.Count & vbCrLf & _
           "列数: " & tbl.Columns.Count
End Sub

表の行数や列数が変わっても、つねに表全体を返してくれます。「データ件数が毎回違う」という場面で重宝するプロパティです。

NOTE

CurrentRegionは保護されたシートでは使用できません。シート保護を設定している場合は注意してください。

ヘッダー行を除いてデータ部分だけを操作する

実務では「見出し行を除いたデータ部分だけ」を処理したい場面が多いです。Offset と Resize を組み合わせると実現できます。

Sub DataWithoutHeader()
    Dim tbl As Range 'テーブル全体

    Set tbl = Range("A1").CurrentRegion

    '--- 1行下にずらして、行数を1つ減らす ---
    tbl.Offset(1, 0).Resize(tbl.Rows.Count - 1, _
        tbl.Columns.Count).ClearContents

    MsgBox "データ部分をクリアしました"
End Sub

処理の流れを整理すると、次のようになります。

  1. CurrentRegion で見出し行を含む表全体を取得
  2. Offset(1, 0) で1行下にずらす(見出し行をスキップ)
  3. Resize(行数 - 1) で行数を1つ減らす(はみ出し防止)

このパターンはよく使うので、ぜひ覚えておいてください。

VBA Rangeのプロパティとメソッド

Rangeで指定したセルに対して使える、主なプロパティとメソッドを紹介します。

よく使うプロパティ

プロパティ説明使用例
.Valueセルの値を取得・設定Range("A1").Value = 100
.Text表示文字列を取得(読み取り専用)MsgBox Range("A1").Text
.Formula数式を取得・設定Range("A1").Formula = "=SUM(B1:B10)"
.Fontフォント設定(色・太字・サイズ等)Range("A1").Font.Bold = True
.Interiorセルの塗りつぶしRange("A1").Interior.Color = vbYellow
.NumberFormat表示形式Range("A1").NumberFormat = "#,##0"
.Row / .Column行番号・列番号を取得MsgBox Range("C5").Row → 5
.Addressセルのアドレスを取得MsgBox Range("A1").Address → $A$1

よく使うメソッド

メソッド説明使用例
.Selectセルを選択Range("A1").Select
.CopyセルをコピーRange("A1").Copy Range("B1")
.Clear値・書式をすべて消去Range("A1:C10").Clear
.ClearContents値だけ消去(書式は残す)Range("A1:C10").ClearContents
.Deleteセルを削除Range("A1").Delete Shift:=xlUp
.AutoFillオートフィルRange("A1").AutoFill Range("A1:A10")

TIP

.Value2 は日付型や通貨型を経由せず、Doubleとしてそのまま返します。型変換が不要なぶん処理速度が速いので、大量データを扱うときは .Value2 がおすすめです。

プロパティの使用例

Sub PropertyDemo()
    '--- A1セルに値を入力 ---
    Range("A1").Value = "売上データ"

    '--- A1セルを太字+赤文字にする ---
    Range("A1").Font.Bold = True
    Range("A1").Font.Color = vbRed

    '--- B1セルに数式を入力 ---
    Range("B1").Formula = "=SUM(B2:B10)"

    '--- B1セルの表示形式を桁区切りにする ---
    Range("B1").NumberFormat = "#,##0"
End Sub

メソッドの使用例

Sub MethodDemo()
    '--- A1:C10をコピーしてE1に貼り付け ---
    Range("A1:C10").Copy Range("E1")

    '--- A列の値だけクリア(書式は残す) ---
    Range("A:A").ClearContents
End Sub

VBA Rangeを使った実務活用パターン

基本を押さえたところで、実務で使える具体的なコードを見ていきましょう。

パターン1: 表の見出し行を書式設定する

Sub FormatHeader()
    Dim rngHeader As Range '見出し範囲

    Set rngHeader = Range("A1:E1")

    With rngHeader
        .Value = Array("日付", "部署", "品目", "数量", "金額")
        .Font.Bold = True
        .Interior.Color = RGB(68, 114, 196)
        .Font.Color = vbWhite
        .HorizontalAlignment = xlCenter
    End With
End Sub

With ステートメントを使うと、同じ範囲への操作をまとめて書けます。Range指定の繰り返しが不要になるので、コードが読みやすくなりますよ。

パターン2: 特定の範囲のデータをクリアする

入力フォームのリセットボタンなどで使えるパターンです。

Sub ClearInputArea()
    '--- 入力エリア(B2:D20)の値だけクリア ---
    Range("B2:D20").ClearContents

    '--- カーソルを先頭に戻す ---
    Range("B2").Select

    MsgBox "入力エリアをクリアしました"
End Sub

.ClearContents なら罫線や色を残したまま値だけ消せます。.Clear だと書式ごと消えるので注意してください。

パターン3: セル範囲を別シートにコピーする

データを別シートに転記する場面で使えるコードです。

Sub CopyToSheet()
    Dim wsFrom As Worksheet '転記元
    Dim wsTo As Worksheet   '転記先

    Set wsFrom = Worksheets("データ")
    Set wsTo = Worksheets("レポート")

    '--- A1:E20をレポートシートのA1に貼り付け ---
    wsFrom.Range("A1:E20").Copy wsTo.Range("A1")

    MsgBox "コピーが完了しました"
End Sub

別シートを操作するときはシートの明示が必須です。

パターン4: Range(Cells, Cells)で動的に範囲を指定する

データの件数が変わっても対応できるよう、最終行を取得して範囲を動的に決めるパターンです。

Sub DynamicRange()
    Dim lastRow As Long '最終行

    '--- A列の最終行を取得 ---
    lastRow = Cells(Rows.Count, 1).End(xlUp).Row

    '--- A1から最終行のC列までに罫線を引く ---
    Range(Cells(1, 1), Cells(lastRow, 3)).Borders.LineStyle = xlContinuous

    MsgBox "罫線を引きました(" & lastRow & "行目まで)"
End Sub

Cells(Rows.Count, 1).End(xlUp).Row は最終行取得の定番です。シートの最下行から上方向に検索して、最初にデータがあるセルの行番号を返します。End プロパティは Excelの Ctrl + 矢印キー と同じ動きです。xlUp(上方向)のほか xlDownxlToLeftxlToRight も指定できます。

最終行の取得方法について詳しくは「最終行を取得する3つの方法」をチェックしてみてください。

Range(Cells(開始), Cells(終了)) の形なら、開始位置も終了位置も変数で制御できます。

NOTE

Cellsは行番号・列番号を数値で指定するプロパティです。RangeとCellsの詳しい使い分けは「RangeとCellsの使い分け」で解説しています。

パターン5: For EachでRangeをループ処理する

Range内のセルを1つずつ処理するには、For Each が便利です。

Sub HighlightNegative()
    Dim rng As Range  '対象範囲
    Dim cell As Range '個別セル

    Set rng = Range("B2:B20")

    For Each cell In rng
        '--- マイナスの値を赤文字にする ---
        If IsNumeric(cell.Value) Then
            If cell.Value < 0 Then
                cell.Font.Color = vbRed
            End If
        End If
    Next cell
End Sub

For Each は「範囲内のセルを順番に取り出す」構文です。行番号を気にせず書けるのがメリットですね。

For Each の詳しい使い方は「For Eachでセル・シートを一括処理」で解説しています。

TIP

For Each の処理順序は「左から右、上から下(行優先)」が一般的です。ただし公式ドキュメントでは順序が保証されていません。順序が重要な処理ではFor文を使いましょう。

よくあるエラーと対処法

Rangeで遭遇しやすいエラーをまとめました。

エラー原因対処法
実行時エラー1004別シートのRangeとCellsでシート指定が食い違っているWith の中で .Range(.Cells(...)) とドットを付ける
実行時エラー1004(Rangeメソッド失敗)Range内の文字列が不正(全角文字混入など)セル番地に全角文字がないか確認する
実行時エラー9存在しないシート名を指定しているシート名のスペルを確認する
実行時エラー91Range型変数に Set を付けずに代入Set rng = Range("A1") と書く
マクロが保存できない.xlsx 形式で保存しようとしている.xlsm 形式で保存する

別シート操作時のエラーを防ぐコード

別シートのセルを操作するときに起きやすいエラー1004の正しい書き方です。

Sub CrossSheetExample()
    '--- エラーが起きるコード ---
    ' Sheets("Sheet2").Range(Cells(1, 1), Cells(10, 3)).Select
    '--- CellsがActiveSheetを参照してしまう ---

    '--- 正しいコード ---
    With Sheets("Sheet2")
        .Range(.Cells(1, 1), .Cells(10, 3)).Select
    End With
End Sub

With の中で .Cells とドットを付ければ、CellsもSheet2を参照するようになります。

Set忘れを防ぐコード

Range型の変数に代入するときは Set が必須です。

Sub SetExample()
    Dim rng As Range '対象範囲

    '--- 正しい ---
    Set rng = Range("A1:C10")

    '--- エラーになる ---
    ' rng = Range("A1:C10")  ← Setがないとエラー
End Sub

Cellsプロパティとの違い・使い分け

Rangeと並んでよく使われるのがCellsプロパティです。

項目RangeCells
指定方法文字列("A1" 形式)数値(行番号, 列番号)
範囲指定Range("A1:C10") で直接指定単体では1セルのみ
名前定義Range("売上合計") で対応非対応
変数との相性文字列結合が必要数値を直接渡せる
ループ処理やや書きにくい行・列を変数で制御しやすい

使い分けのポイントは次のとおりです。

  • 固定のセル範囲 → Range
  • 名前定義の参照 → Range
  • 変数でセル位置を動かす → Cells
  • ループ処理 → Cells
  • 動的な範囲指定 → Range(Cells, Cells) の組み合わせ

TIP

迷ったら「固定範囲はRange、ループはCells」と覚えておけばOKです。詳しくは「RangeとCellsの使い分け」をチェックしてみてください。

まとめ

VBA Rangeプロパティの使い方を振り返りましょう。

  • Range(“A1”) で単一セル、Range(“A1:C10”) で範囲を指定
  • 行全体は Range(“1:1”)、列全体は Range(“A:A”)
  • Offset で基準セルからの相対位置を参照
  • Resize で範囲サイズを動的に変更
  • CurrentRegion で表全体を自動取得
  • Range(Cells, Cells) で動的な範囲指定
  • 別シートの操作は シートオブジェクトを明示
  • Range型変数への代入は Set を忘れずに

Rangeはセル操作の出発点です。Offset・Resize・CurrentRegionまで使いこなせると、データ件数に左右されない柔軟なマクロが書けるようになります。ぜひVBEを開いて試してみてください。

関連記事

タイトルとURLをコピーしました