Rangeの中でCellsの書き方が分からない原因

Rangeプロパティの引数に”A1″などのセル座標の文字列を使っている場合と、Cells(1, 1)のようにCellsプロパティを使っていることがあります。

問題はその書き方です。

引数に座標だけを書いてある場合はこんな感じです。これはA1セルと分かります。
Range(“A1“)

引数に「Cells」使っている場合はこんな感じです。
Range(Cells(1,1))
Range(Cells(1,1), Cells(2,2))

このようなRangeとCellsを組み合わせた書き方だと、Cells(1, 1)はなんとかA1と分かりますが、Cells(15, 31)とかなってくるとどの座標なのか直感的には分かりにくくなります。

この問題点は、Rangeの引数には「”A1″ なのか、Cellsなのか、Range(“A1”)なのか、カンマ区切りで書いたらどうなるのか、など、どう書いたらいいのか分からない」点です。その部分を後述していきます。

Rangeの引数の構文

上の”A1″での書き方もCellsプロパティを使った書き方も、どちらも構文としてはこのようになります。

Property Range(Cell1, [Cell2]) As Range

Cell1 起点となるセル座標を文字列で指定するかRangeオブジェクトで指定します。Cell2を省略する場合はRangeオブジェクトは指定できません。”Cell1″というのは単に引数の名前なだけでCellsプロパティとは関係ありません。
Cell2 2つ目の起点となるセル座標を文字列で指定するかRangeオブジェクトを指定します。”Cell2″というのは単に引数の名前なだけでCellsプロパティとは関係ありません。省略可能です。省略した場合はCell1で指定したセルが参照対象になります。
戻り値 Cell1とCell2で指定したセルを起点とするセル範囲のRangeオブジェクトを返します。

上の説明を実際のRangeメソッドの構文に直すと、具体的には以下の6パターンに限定されます

これら以外の書き方はありません。引数は”セル座標文字列”かRangeオブジェクトの2種類しかありません。

引数を1つだけ指定する場合

  • Property Range(“セル座標文字列”) As Range
    例:Range(“A1”)
  • Property Range(“セル座標文字列:セル座標文字列”) As Range
    例:Range(“A1:B3”)

引数を2つ両方指定する場合

  • Property Range(“セル座標文字列”, “セル座標文字列”) As Range
    例:Range(“A1”, “B3”) ※Range(“A1:B3”)と同じ結果になる。書き方が違うだけ。
  • Property Range(Rangeオブジェクト, Rangeオブジェクト) As Range
    例1:Range(Range(“A1”), Range(“B3”))
    例2:Range(Cells(1, 1), Cells(3, 2))
  • Property Range(“セル座標文字列”, Rangeオブジェクト) As Range
    例:Range(“A1”, Range(“B3”))
  • Property Range(Rangeオブジェクト, “セル座標文字列”) As Range
    例:Range(Range(“A1”), “B3”)

引数のセル座標文字列は、”A1″、のような文字列だけでなく、Range(“A1”).Address(False, False)、や、Cells(1, 1).Address、などのようにAddressプロパティを使うなどでセル座標を指定する文字列に結果的になるのであれば許可されます。

引数のRangeオブジェクトは、「Range(“A1”)」と書いた場合も「Cells(1, 1)」と書いた場合も対象になります。

この構文の説明を見てすぐに分かるのであれば以降の説明は不要だと思いますが、そうでない方は一通り最後まで読んでみてください

分かりにくい理由には大きく2つあり、1つはCellsプロパティの定義が分かりにくいことと、もう1つはRangeプロパティとCellsプロパティの違いを認識できていないことにあります。

RangeプロパティとCellsプロパティの違い

RangeプロパティとCellsプロパティはどちらもセルを表すプロパティです。ただ、用途が異なります。

具体的には以下のようになります。

プロパティ 用途
Cells 単一セルを参照する。引数は縦位置と横位置の両方を指定する。引数省略時はシートの全セルを参照する。
Range セル範囲を1つまたは複数参照する。引数は起点となるセルを1つまたは2つ指定する。複数のセル範囲を参照する場合はカンマで区切る。

Cellsプロパティは引数で指定した縦位置(行)と横位置(列)が重なる1つのセルしか参照できませんが、Rangeプロパティはセル範囲や複数の選択範囲を同時に参照できます。

例えば、D2セルをCellsプロパティを使って選択する場合は、「Cells(2,4).Select」と書きます。

また、「B3~C4」「D2~F6」「A5」セルの3つの選択範囲をRangeプロパティで選択する場合は「Range(“B3:C4,D2:F6,A5”).Select」と書きます。

このように、単一セル用のCellsプロパティとセル範囲用のRangeプロパティとして違いがあります。

RangeとCellsの書き方一覧

RangeとCellsの書き方にはいくつかのパターンに絞られます。

例:A1セルのみ

なお、「Range(Range(“A1”)」や「Range(Cells(1, 1))」の2つがエラーになるのは、2番目の引数を省略しており1番目の引数だけを指定した場合にはセル座標文字列を指定しなければならないためです。2番目引数省略時にRangeオブジェクトを指定するとエラーになります。

例:A1からC12のセル範囲

2番目の引数がある場合は、1番目の引数にセル座標文字列だけでなくRangeオブジェクトを指定することが出来るようになります。

なお、Offsetプロパティを使うと相対座標の考え方が加わり、いろんな書き方ができるようになります。

例:A1セルのみ(Offsetプロパティで基準セルからの相対座標を指定する)

例:A1からC12のセル範囲(Offsetで相対座標指定)

Range(Cell1, [Cell2]) の使い方

Range(Cell1, [Cell2])の使い方は、上のRangeとCellsの書き方一覧のどれかの書き方で書けばいいです。そのため、Range(Cell1, Cell2)の引数のCell1とCell2にはRangeでもCellsでもどっちを使ってもいいことが分かります。

CellsプロパティとRangeプロパティで用途は異なりますが、Cellsプロパティの書き方で迷いやすかったり分かりにくいと感じるのであれば無理にCellsプロパティを使う必要はありません。Rangeプロパティだけを使う書き方でもセル操作を行うことは可能ですし、Cellsを使わないからといってプログラムが難解になったりすることもありません。その逆で、Cellsを使うからといってプログラムがやさしくなることもありません。

A1セルを参照する書き方で、「Range(“A1”)」と「Cells(1, 1)」のどちらが分かりやすいかと聞かれれば、多くの人はRange(“A1”)と答えると思います。A1って書いてますからね。

Cellsプロパティでの書き方には混乱をまねく点がいくつかあります

1つ目は、上に書いた通りですが直感的に分かりにくいという点です。括弧の引数は(縦位置, 横位置)を指定しますが、縦位置と横位置が左上から1を基準としていることを知っておかなければ使えません。また、多くの人がセル座標を「A1」などと、横→縦、の順で認識しているのですが、Cellsプロパティの引数は逆の縦、横の順です。そのため、A5セル→Cells(5, 1)と縦横を逆に書くことにストレスが発生します。

2つ目は、Cells(1, 1)と書いたあとにドットを押してもメソッドやプロパティの候補が表示されないことです。候補が表示されないのは「Cells(y, x)」のメソッド定義がVBAで存在しないためです。候補が表示されないため、本当にこの書き方で正しいのかが確証とれません。候補が表示されない理由や対応方法の詳細は「VBAでドット(.)を押しても入力候補が出ない場合」をご参照ください。

3つ目は、「Cells」と「Cells(1, 1)」は全く用途が違うのに同じ名前のプロパティが使われている点です。「Cells」だけで書くとシートの全セルを対象としますが、「Cells(y, x)」と書くと単一セルを対象とします。Cells=シート全体、とは直感的には分かる人はそうそういないでしょう。

このようにCellsプロパティには混乱をまねく点があるため、使いづらさなどを感じるのであれば、Rangeプロパティを使って読みやすい安全なプログラムを書くことをお勧めします。Cellsプロパティの方が高速ではありますが微々たるもので多くの場合は気にする必要はありません。なぜCellsの方が高速なのかについては「VBAの高速化(RangeとCellsの使い分け)」をご参照ください。

そして、これはおまけに過ぎませんが、私自身、Cellsプロパティを使うことはほとんどありません。Rangeの方が使いやすいので。