【VBA】RangeとCellsの違いと使い分け|実務別に解説

スポンサーリンク

Excel VBAでセルを操作するとき、RangeとCellsのどちらを使うか迷いませんか。

書き方がまったく違うので、「結局どっちが正解なの?」と手が止まりがちですよね。使い分けを間違えると、ループ処理でセル番地の文字列結合が必要になったり、別シート操作で1004エラーに悩まされたりします。

この記事では、RangeとCellsの違いを比較表で整理し、実務シナリオごとの選び方をお伝えします。読み終わるころには「この場面ならこっち」と迷わず選べるようになりますよ。

NOTE

VBAを初めて触る方は、先に「VBE画面の見方」をチェックしておくとスムーズです。

RangeとCellsの違いを一覧でおさらい

まず結論から整理しましょう。RangeとCellsはどちらも「セルを指定する方法」ですが、得意な場面が違います。

比較項目RangeCells
書き方Range("A1")Cells(1, 1)
指定方法アドレス文字列行番号・列番号(数値)
複数セル範囲Range("A1:C10") で直接指定単体では1セルのみ
名前付き範囲Range("売上合計") で参照可非対応
変数との相性文字列結合が必要数値をそのまま渡せる
ループ処理やや冗長になるスッキリ書ける

ひとことで言えば、「文字列で指定するか、数値で指定するか」の違いです。この違いが使い分けの根拠になっています。

Range:アドレス直書きでわかりやすい

RangeはExcelシート上の「A1」形式をそのまま使えます。普段のExcel操作と同じ感覚なので、直感的に読み書きできるのが強みです。

' 1つのセルに値を入力
Range("A1").Value = "こんにちは"

' 範囲をまとめて太字にする
Range("A1:C10").Font.Bold = True

' 離れたセルを一括指定
Range("A1,C3,E5").Font.Color = vbRed

Rangeの詳しい使い方は「VBA Rangeの使い方」でも解説しています。

Cells:行番号・列番号で指定できる

Cellsは行と列を数値で指定します。「Cells(行, 列)」の形で、列もアルファベットではなく数字で書くのがポイントです。

' A1セル(1行目・1列目)に値を入力
Cells(1, 1).Value = "こんにちは"

' B3セル(3行目・2列目)に値を入力
Cells(3, 2).Value = 100

数値だけで指定するので、変数と組み合わせやすいのが最大の強みです。

VBA Cellsを使うべき場面

Cellsが本領を発揮するのは、セルの位置を動的に変えたいときです。

For文でループするとき

Cellsの最大の強みは、変数をそのまま行番号に渡せることです。

' A列の1行目〜10行目に連番を入力
Dim i As Long
For i = 1 To 10
    Cells(i, 1).Value = i
Next i

同じ処理をRangeで書くとこうなります。

' Rangeだと文字列結合が必要
Dim i As Long
For i = 1 To 10
    Range("A" & i).Value = i
Next i

動きは同じですが、"A" & i と文字列結合が入ります。列も変数にしたい場合はさらに複雑になるので、ループ処理ではCellsがおすすめです。

For文の書き方をもっと知りたい方は「VBA For文の使い方」もチェックしてみてください。

行列を動的に計算したいとき

行も列も変数で動かしたい場合、Cellsの数値指定が活きます。

' 5×5の掛け算表を作る
Dim r As Long  ' 行カウンター
Dim c As Long  ' 列カウンター
For r = 1 To 5
    For c = 1 To 5
        Cells(r, c).Value = r * c
    Next c
Next r

二重ループとの相性は抜群です。Rangeでこれをやると、列番号をアルファベットに変換する処理が必要になり、かなり面倒になります。

変数(Dim)の宣言ルールが気になる方は「変数の使い方とルール」を参照してください。宣言を強制するOption Explicitもあわせて覚えておくと安心ですよ。

VBA Rangeを使うべき場面

一方、Rangeが適しているのは「セルの位置が決まっている」場面です。

セルアドレスが固定のとき

操作対象が固定セルなら、Rangeが読みやすいです。

' 決まったセル範囲をクリアする
Range("A1:D1").ClearContents

' ヘッダー行を太字にする
Range("A1:F1").Font.Bold = True

「A1:D1」とそのまま書けるので、コードを読んだ人がすぐに対象範囲を把握できます。可読性の高さがRangeの大きなメリットです。

名前付き範囲を指定するとき

Excelで名前を定義している場合、Rangeから直接参照できます。

' 名前定義「売上合計」の値を取得
Dim total As Long
total = Range("売上合計").Value

名前付き範囲はCellsでは参照できません。名前定義を使う場面ではRangeの一択になります。

セルの位置が変わってもコードを修正しなくて済むので、実務ではとても便利ですよ。

Range(Cells, Cells)の組み合わせ技

RangeとCellsは組み合わせて使えます。これを覚えると、動的な範囲指定がぐっと楽になります。

基本構文

Range(Cells(開始行, 開始列), Cells(終了行, 終了列)) の形で書きます。

' A1からE10までを選択
Range(Cells(1, 1), Cells(10, 5)).Select

開始位置も終了位置も数値で制御できるのがポイントです。固定範囲にはRange単体、動的範囲にはこの組み合わせと覚えておきましょう。

開始・終了行を動的に変える実例

実務で最もよく使うのが、最終行を取得して動的に範囲を決めるパターンです。

Sub 動的範囲に罫線を引く()
    ' A列の最終行を取得
    Dim lastRow As Long
    lastRow = Cells(Rows.Count, 1).End(xlUp).Row

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

ちょっとむずかしく見えますが、やっていることはシンプルです。Cells(Rows.Count, 1).End(xlUp).Row でA列の一番下から上に向かって最終行を探しています。

データの件数が増減しても自動で対応できるので、実務では非常に重宝します。最終行の取得方法をもっと詳しく知りたい方は「最終行を取得する3つの方法」もどうぞ。

もうひとつ、可変範囲をコピーする実例も見てみましょう。

Sub データ範囲をコピーして貼り付ける()
    Dim lastRow As Long
    Dim lastCol As Long

    ' データの最終行・最終列を取得
    lastRow = Cells(Rows.Count, 1).End(xlUp).Row
    lastCol = Cells(1, Columns.Count).End(xlToLeft).Column

    ' データ範囲をまるごとコピー
    Range(Cells(1, 1), Cells(lastRow, lastCol)).Copy

    ' Sheet2のA1に貼り付け
    Sheets("Sheet2").Range("A1").PasteSpecial xlPasteValues
    Application.CutCopyMode = False
End Sub

最終行だけでなく最終列も動的に取得すれば、列が増えても自動で対応できます。

実務シナリオ別の選択ガイド

ここまでの内容を、よくある実務シナリオで整理しましょう。

一覧表を上から順に処理する

請求書データや社員名簿を1行ずつ処理するパターンです。

Sub 一覧表を順に処理する()
    Dim lastRow As Long
    lastRow = Cells(Rows.Count, 1).End(xlUp).Row

    Dim i As Long
    For i = 2 To lastRow  ' 2行目から(1行目はヘッダー)
        ' B列が空欄ならスキップ
        If Cells(i, 2).Value <> "" Then
            ' D列に計算結果を入力
            Cells(i, 4).Value = Cells(i, 2).Value * Cells(i, 3).Value
        End If
    Next i
End Sub

行を変数 i で動かすのでCells一択です。「For文」と「For Each」のどちらでもCellsが活躍します。条件分岐を入れたいときは「Do Loop」との組み合わせも検討してみてください。

可変範囲をまるごとコピーする

データの最終行・最終列が変わる範囲を一括操作するパターンです。

Sub 可変範囲を書式設定する()
    Dim lastRow As Long
    Dim lastCol As Long
    lastRow = Cells(Rows.Count, 1).End(xlUp).Row
    lastCol = Cells(1, Columns.Count).End(xlToLeft).Column

    ' データ範囲全体に背景色をつける
    Range(Cells(2, 1), Cells(lastRow, lastCol)).Interior.Color = RGB(230, 240, 255)
End Sub

Range(Cells, Cells)の組み合わせが最適です。開始・終了を変数で制御しつつ、範囲全体をまとめて操作できます。

集計行をループの外に固定する

ヘッダーや集計行など、位置が固定のセルを操作するパターンです。

Sub 集計処理()
    Dim lastRow As Long
    lastRow = Cells(Rows.Count, 1).End(xlUp).Row

    ' ループ部分はCells
    Dim total As Long
    Dim i As Long
    For i = 2 To lastRow
        total = total + Cells(i, 3).Value
    Next i

    ' 固定セルへの書き込みはRange
    Range("A1").Value = "集計結果"
    Range("B1").Value = total
End Sub

ループ内はCells、固定セルはRangeと使い分けるのがスマートです。コードの意図が明確になり、後から読んでも何をしているか一目でわかります。

シナリオ別まとめ表

シナリオおすすめ理由
一覧を上から順に処理Cells行番号を変数で動かす
可変範囲を一括操作Range(Cells, Cells)動的な開始・終了を範囲指定
固定セルへの読み書きRangeアドレス直書きで可読性が高い
名前付き範囲の参照RangeCellsでは名前定義を参照できない
二重ループ(行×列)Cells行列ともに数値で制御できる

1004エラーの原因と対処法

RangeとCellsの組み合わせで最もハマりやすいのが、実行時エラー1004(「アプリケーション定義またはオブジェクト定義のエラー」)です。

Worksheetオブジェクトの明示

このエラーは、別シートのCellsをRange引数に渡すときに起きます。

' エラーになるコード
Sheets("Sheet2").Range(Cells(1, 1), Cells(10, 3)).Select

一見すると正しく見えますが、問題があります。Range は Sheet2 を指していますが、Cells はアクティブシートを指しています。シートの参照先がバラバラなのでエラーになるのです。

正しくはこう書きます。

' 正しいコード:Withでシートを統一する
With Sheets("Sheet2")
    .Range(.Cells(1, 1), .Cells(10, 3)).Select
End With

ポイントは .Range.Cells の先頭にドット(.)をつけることです。ドットをつけると、Withで指定したSheet2のプロパティとして認識されます。

ドットを1つでも忘れるとエラーになるので注意してください。

もうひとつ、シートを変数に入れて書く方法もあります。

' 変数でシートを指定する方法
Dim ws As Worksheet
Set ws = Sheets("Sheet2")
ws.Range(ws.Cells(1, 1), ws.Cells(10, 3)).Select

どちらの書き方でもOKです。大事なのは「Range・Cells・すべてのシート参照を揃える」ことです。

NOTE

1004エラーは実行時に発生するため、コードを書いた時点では気づけません。別シートを操作するコードを書いたら、必ずテスト実行して確認しましょう。

まとめ:迷ったときの使い分け早見表

RangeとCellsの使い分けを最終確認しましょう。

やりたいこと使うもの書き方の例
固定セルに値を入れるRangeRange("A1").Value = 100
名前付き範囲を参照RangeRange("売上合計").Value
ループで行を動かすCellsCells(i, 1).Value
行列ともに変数で動かすCellsCells(r, c).Value
動的範囲を一括操作Range + CellsRange(Cells(1,1), Cells(lastRow,3))
別シートのセルを操作With + ドット付き.Range(.Cells(1,1), .Cells(10,3))

判断に迷ったら、次の順番で考えてみてください。

  1. 名前付き範囲を使う? → Range
  2. セルの位置が固定? → Range
  3. 変数で位置を動かす? → Cells
  4. 動的な範囲指定? → Range(Cells, Cells)

どちらが正解ということではなく、場面で使い分けるのがベストです。VBAに慣れてくると自然とCellsを使う場面が増えてきます。

ぜひVBEを開いて、両方のコードを試してみてくださいね。

関連記事

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