候補が出ないのは候補を出すべきクラスが分からないから
VBAで各種オブジェクトの後ろでドット(.)を押すとメソッドやプロパティが表示されます。ところが同じようにドット(.)を入力しても入力候補が出ない場合があります。よく目にするのはSelectionやCells(x, x)などですね。
出ないのにはもちろん理由があります。候補が出ないのは候補を出すべきクラスが分からないためです。
RangeクラスだったらValueやTextプロパティ、ShapeクラスだったらNameやTitleなどのプロパティがあるとわかるのですが、何のクラスなのか分からないと出しようがありません。SelectionやCells(x, x)という記述ではクラスが分からない状態なんです。
そのままでは入力候補を出すことは出来ませんが別の方法で候補を出すことは出来ます。
SelectionとCells(x, x)のそれぞれにおいて、候補が出ない理由と候補を出す方法を説明します。
Selectionの候補が出ない理由
「Selection」は何を選択しているかによって内容が変わります。具体的にはセルを選択しているのか、オートシェイプを選択しているのか、などの違いです。
「Selection」だけでは何を選択しているのかはコード上は分かりません。マクロを実行するまで何が選択されているのか分からないのです。
セルの場合はRangeクラス、オートシェイプの場合ではDrawingObjectsと異なり、当然メソッドやプロパティも異なります。そのため候補を出せません。
そこで、以下のように何を選択しているのかを明示することで候補表示ができるようになります。
Selectionの候補を出す方法
1. セル範囲を選択している場合のSelection
セル範囲を選択している場合のSelectionはRangeオブジェクトになります。
そこで、明示的にRangeオブジェクトの変数に代入します。
以下のようにSelectionをRangeクラスのオブジェクト変数に代入すると、その変数にドット(.)を入力すれば入力候補が表示されるようになります。
4行目がその代入部分です。オブジェクトへの代入のためSetステートメントでの代入になります。
1 2 3 4 5 6 7 8 |
Dim sel As Range Dim r As Range Set sel = Selection For Each r In sel Debug.Print r.Address Next |
2. オートシェイプを選択している場合のSelection
上のセル範囲の場合と同様で、オートシェイプを選択している場合のSelectionはDrawingObjectsオブジェクトになります。
ただ、DrawingObjectsオブジェクトは古い形式で内部的には存在しているのですが、DrawingObjectsクラスは入力候補が出ません。
そのため、DrawingObjectsクラスの後継クラスであるShapeRangeクラスを利用します。ShapeRangeクラスは入力候補が表示されます。
ShapeRangeクラスのオブジェクト変数に代入するには、Selection(ここではDrawingObjectsオブジェクト)のShapeRangeプロパティを使います。こちらもオブジェクトへの代入のためSetステートメントでの代入になります。
あとは、ShapeRangeオブジェクトとしてドット(.)で入力候補が表示されるようになります。
1 2 3 4 5 6 7 8 |
Dim sr As ShapeRange Dim shp As Shape Set sr = Selection.ShapeRange For Each shp In sr Debug.Print shp.Name Next |
Cells(x, x)の候補が出ない理由
簡単に言うと、「Cells=Rangeオブジェクト」、「Cells(x, x)=Variant=クラス未定」という違いにより候補表示できません。
「Cells」と入力してドット(.)を入力すると候補表示されます。「Cells」がRangeオブジェクトを返すためです。
CellsとRangeは定義上はこうなっています。
1 2 |
Property Cells As Range Property Range(Cell1, [Cell2]) As Range |
Cells(x, x)は定義として存在しません。Rangeは逆で、「Range」だけの定義は存在しません。
「Cells(」と入力すると「_Default([RowIndex], [ColumnIndex])」と出てきます。
これはCellsがRangeクラスのため、そのRangeクラスの初期値候補の_Defaultが表示されます。
しかし、その初期値である([RowIndex], [ColumnIndex])を入力して「Cells(x, x)」の形になると上記の通り定義されていないため、候補が表示されないことになります。
本来であれば、「Cells」の定義は以下のような定義が正しい形なんでしょうけど、これが無いのは個人的にはVBAの設計漏れだろうと思います。
1 |
Property Cells(RowIndex, ColumnIndex) As Range |
Cells(x, x)の候補を出す方法
1. Rangeオブジェクト変数に代入する
上のSelectionの場合と同じです。Rangeオブジェクト変数に代入します。オブジェクトへの代入のためSetステートメントでの代入になります。
あとは代入後のRangeオブジェクトの変数を使えば候補が表示されます。
1 2 3 4 |
Dim r As Range Set r = Cells(1, 1) r.Value = "abc" |
2. Cells のあとにドット(.)を入力する
上にも書きましたが「Cells」と5文字入力したあとにドット(.)を入力すると入力候補が表示されます。
ここで候補を選んで、あとから括弧の中を書く、という方法です。
個人的には面倒なのとCellsはあまり使わないのでこの書き方はしません。一応できます、って感じですね。