Selectionのセル範囲はどの順に格納されているのか

Selectionプロパティは現在選択されているセル範囲を表します。セルだけでなくオートシェイプでも複数選択した場合に利用できますが、ここではセル範囲のSelectionプロパティについて説明します。

Selectionプロパティのセル範囲が格納されている場合、セル範囲の左上から右下のセルに向かって格納されています。正確には1行分の一番左から右まで、そして次の行の、という順です。英字のZの書き順と同じです。

セルを選択する場合、開始セルはセル範囲の四隅(左上、右上、左下、右下)のどこからで範囲選択可能ですが、いずれの場合も、Selectionは一番左上のセルが先頭に格納され、一番右下のセルが最後になります

セル範囲のSelectionプロパティのセルを1つずつ処理する場合、For Eachを使って1つずつ取り出すのが一番簡単な方法です。

実行結果
C5
D5
C6
D6
C7
D7

上の絵のように、左上から右下に向かって、ループで取得したセルの座標が出力されます。

開始セルから終了セルに向かって処理をしたい場合

上に書いたとおり、Selectionプロパティに格納される順は左上のセルから右下のセルに向かって格納されます。

そのため、セル範囲の開始セルから終了セルに向かう順番で処理をしたい場合で、かつ、開始セルが左上でない場合は、開始セルがどこ(右上?左下?右下?のどこ)なのかを考慮する特殊処理が必要になります。

方法としてはCells(行, 列)を使って処理する方法があります。

まず、アクティブセルの座標を取得します。これが開始セルになります。

そのあとに、Selectionプロパティの四隅の座標を取ります。そうすると、アクティブセルが左上、右上、左下、右下のどこなのかを特定できます。

そして、開始セルを特定したとは、対角線上のセルが終了セルと判定できます。

あとは、開始セルから終了セルに向かってCells(行, 列)のRangeオブジェクトを使って処理すれば、開始セルから終了セルの順に処理できます。ただ、このような特殊処理が必要な状況は相当なレアケースと思います。

セル範囲のSelectionプロパティはRangeオブジェクトに変換できる

上のコードではループの書き方で、

For Each r In Selection

と書いています。rはRangeオブジェクトの変数です。

この書き方でもいいですし、私もこのように書くことが多いのですが、SelectionプロパティをRangeオブジェクト変数に代入して書くことも出来ます。

実行結果
C5:D7
C5
D5
C6
D6
C7
D7

最初のコードと違うのは、SelectionプロパティをRangeオブジェクト変数の「sr」に代入して、あとはそれを利用している部分です。

このようにSelectionプロパティをRangeオブジェクトとして代入すると、1つ利点があります。それは、ドット「.」を押したあとにプロパティやメソッド候補が出るようになる点です。

Selectionプロパティ自体には明確なデータ型がありません。セル範囲を示すこともあれば、オートシェイプの選択範囲を示すこともあるので、どちらのデータ型かをSelectionプロパティ自体が持てないためです。

そこで、明らかにセル範囲を示していると分かっている場合はRangeオブジェクト変数に入れてしまえば、あとはRange型として扱えます。