● Access2000VBA・Excel2000VBA独学~「Dim ×× As Object」という変数宣言をしたときなどに、入力候補の自動補完がされない場合の対処法(「TypeName関数」を使って明確なオブジェクト名を調べてから。)
※まだ書きかけです。すみません。
※間違ってたらすみません。
※メモ書きなので、自分でも意味不明な箇所も多いです。ごめんなさい。
★ はじめに
たとえば、操作したいオブジェクトやコレクションの型(というか種類)が事前に分からないときに・・・、
Dim Obj01 As Object
Set Obj01 = オブジェクトやコレクションの参照式
・・・というようなプログラムを書いてしまうことがあります。
で、この場面の「Dim Obj01 As ・・・」で使っている「Object」という単語は、「どんな種類のオブジェクトか分かんないけど、とにかくオブジェクト」という場合に使う、ちょっと苦し紛れの単語です。
どのオブジェクトにも使える「汎用のオブジェクトの名前」・・・、という感じです。
逆に言うと、どんなオブジェクトにも使えるので「チョー便利!」ということもあるんですが(特に初心者のうちは)、ただ、このような感じで、オブジェクト変数の宣言に「Object」という単語を使ってしまうと・・・、実は、変数宣言後にさらにプログラムを書こうとしたときに・・・、例えば「Obj01 」のあとに「.(ドット)」を入力しても、入力候補の自動補完機能(IntelliSense機能:インテリセンス機能)が働きません。
入力候補のドロップダウンがニョロニョロニョロっと出てこないのです。
このような場合に、インテリセンス機能を働かせるためには、「Dim Obj01 As Object」の変数宣言で「Object」という単語を使用するのではなく、「Range」「Workseet」「Workbook」とか、「Sheets」「Workbooks」など、明確なオブジェクト名やコレクション名を指定します。
※この場合、「データ型」としては、「Object」でも「Range」でも「Workseet」でも「Workbook」でも「Sheets」でも、「オブジェクト型」になるんだと思います・・・。
★ 「TypeName関数」を使って、どんな種類のオブジェクトなのかを調べる
ただ、その場合、特にExcelの場合は『 ”プロパティ経由”でオブジェクトやコレクションを取得するというケースが多い』んですが、そのときに『プロパティ名からオブジェクト名を想像できない場合も多い』ため、ちょっと悩んでしまいます。
セルってどんなオブジェクト名を使えばいいの???
とか。
例えば(セル範囲のことを)、「Cells(1,1)」と「Cellsプロパティ」で書いたり、「Activecell.Offset(3,3)」と「Offsetプロパティ」で書いたりした場合に取得できるオブジェクトは「Rangeオブジェクト」ですが、その時「Cells」や「Offset」といった名前から「Range」という名前は普通は想像がつきません。(慣れていないと。)
特に、僕みたいなド素人とか、VBA初心者の方々は。
もちろん、セルのことを「Range("A1")」みたいに、「Rangeプロパティ」で書いて、オブジェクトとして取得する場合もありますので、その場合はRangeかな?と想像はつきますが、いつも、うまくいくとは限りません。
同様に、例えば「ActiveWorkbook.Worksheets」という感じで書いたときにその「Worksheetsプロパティ」で取得できるオブジェクトは、「Sheetsオブジェクト」(コレクションとしてのオブジェクト)ですが、「Worksheets」という名前から「Sheets」という名前は想像がつきません。
このような感じで、(コレクション経由ではなく)プロパティ経由でオブジェクトを取得するときに、その取得したオブジェクトを調べるのには、「TypeName関数」が便利です。(メソッド経由でオブジェクトを取得する場合も同様です。)
例えば「TypeName関数」をVBEのイミディエイトウィンドウで使うと、取得できたオブジェクトがどんな種類のオブジェクトなのかがわかります。
例えば以下のように使います。
例えば・・・、
? TypeName(ActiveWorkbook.Worksheets)
? TypeName(Worksheets)
・・・などと打ち込んでEnterすると「Sheets」という単語が表示されます。(返ってきます。)
そのほか・・・、
? TypeName(Cells(1,1))
? TypeName(Activecell.Offset(3,3))
? TypeName(Range("A1"))
・・・などと打ち込んでEnterすると「Range」という単語が表示されます。(返ってきます。)
このように、TypeName関数で返ってきた単語が、『プロパティやメソッド・コレクション経由でオブジェクト(または更にコレクション)の取得をした際に、返ってきた名前』です。
※補足
前述したように、VBEのイミディエイトウィンドウに・・・
? TypeName(Worksheets)
・・・と書いてEnterしたとき、『返ってきそうなのは「Worksheets」かな?』と想像してしまいがちなんですが、実際に返って来るオブジェクト名は「Sheets」です。(Sheetsコレクションの名前)
「Sheets」は、グラフシートもワークシートもその他のシートも、全部含めた集まり・・・、つまり、作業中のブックにあるすべてのシートのコレクション・・・・、と、そういうオブジェクトです。
このように、「実は想像と違ってた」ということもあるので、TypeName関数でオブジェクトの種類(=オブジェクト名)を調べる、というのは初心者の方々にとって、とても力強い味方になってくれます。
オブジェクトの階層構造を調べたり理解したり、ひいては、ヘルプの理解、さらにひいては、それをベースにしたエラー対応・トラブル解決、にもとても役に立ちます。
※参考
TypeNameプロパティだけではなくVBE(Visual Basic Editor)の「ローカルウィンドウ」を使って、ステップ実行することで調べることもできます。
★ 「TypeName関数」で調べたオブジェクト名を、「Dim Obj01 As ・・・」に使う。
この「TypeName関数」で調べたオブジェクト名を使って、オブジェクト変数の変数宣言をし直します。
つまり、
「Dim Obj01 As Object」
といった書き方の、
『少しあいまいな意味(汎用な意味)でのオブジェクト変数の宣言』
を、
「Dim Obj01 As Range」
とか、
「Dim Obj01 As Sheets」
といった、
『明確なオブジェクト名やコレクション名で決め打ちしたオブジェクト変数の宣言』
に書き換えます。
そうすると、
「Set Obj01 = オブジェクトやコレクションの参照式」
と書いたあとに、「Obj01 」と書いたとき、
そのあとに「.(ドット)」を打ち込むと、インテリセンス機能のドロップダウンがニョロニョロニョロっと出てくるようになります。
★ 「TypeName」の機能にさらに何らかの機能も追加したいとき
なお、もし、「TypeName」の機能だけじゃなくて、その他の機能をプラスしたい場合は、例えば次のような関数をコピペしてベースとし、あとは、自分で追加したい機能を付け加えます。
1 2 3 4 5 6 7 8 9 |
' ' Function ObjTypeNameChk(ChkObj01 As Object) As String ObjTypeNameChk = TypeName(ChkObj01 ) End Function ' ' |
(なんで最初にこんなの書いたのか・・・わからん・・・↓)
1 2 3 4 5 6 7 8 9 10 11 12 |
' ' Function ObjTypeNameChk02(ChkObj01 As Object) As String Dim TmpObj01 As Object Set TmpObj01 = ChkObj01 ObjTypeNameChk02 = TypeName(TmpObj01) End Function ' ' |
★ Accessでも同じ(未検証ですが多分Wordでも同じ)
これはAccessでも同じです。
例えば、最初に開いたフォームの上に「コマンド0」という名前のコマンドボタンがあったとき、イミディエイトウィンドウで
「? Typename(Forms(0).Controls("コマンド0"))」
とタイプしてEnterすると
「CommandButton」
という単語が返ってきます。
なので、「"コマンド0"というコマンドボタンは"CommandButton"っていうオブジェクトですよ~!」っていうことになります。
Wordでもたぶん同じようにオブジェクト名が調べられるんだと思います。
※補足
AccessではDAOやADOなどを使うことが多いんですが、それらのOfficeの外部機能のプロパティやオブジェクトには使えない気がします。