● Access2000VBA・Excel2000VBA独学~イミディエイトウィンドウで使う自作関数 ★ ~Current無省略オブジェクト式記述~
※まだ書きかけです。すみません。
※間違ってたらすみません。
※メモ書きなので、自分でも意味不明な箇所も多いです。ごめんなさい。
目次
(01)すべての上位のオブジェクト名を一覧表示(「Obchk03Type」という自作関数)
(02)すべての上位のオブジェクトの名前を一覧表示(「Obchk04Name」という自作関数)※Nameプロパティを持つオブジェクトだけ
(03)すべての上位のオブジェクトのインデックス番号を一覧表示(「Obchk05Index」という自作関数)※Indexプロパティを持つオブジェクトだけ
(04)色の数値を「赤・緑・青」の数値に変換する(「GetIntByRGB」という自作関数)
※Shift+TABキー、もしくは、Homeキー、Homeキー+TAB数回、を押すと、目次付近に戻れます。
※関連記事
★Access2000VBA・Excel2000VBA独学~今・選択されてる or 指定したオブジェクトの省略の無い階層構造をさっと調べる自作関数 ~イミディエイトウィンドウで使う自作関数 ★ ~Current無省略オブジェクト式記述02~
★ イミディエイトウィンドウで使う自作関数(ちょっとした省力化)
関数というか、イミディエイトウィンドウなどから呼び出して使う、戻り値が無かったり有ったりのプログラムたちです。僕(ド素人)が作ったやつなのでショボいですが、それなりに使えます。とくにExcel初心者の方向けです。
(01)すべての上位のオブジェクト名を一覧表示(「Obchk03Type」という自作関数)
シート上で選択したオブジェクトの、「すべての上位オブジェクトの(親・ばあちゃん・ひいばあちゃん、ひいひいばあちゃん・・・の)オブジェクト名」がリストアップ表示されます。
使い方は、必ず、オブジェクト式を知りたいオブジェクト(グラフ上の何かやセルなど)を画面上で選択してから、VBE(Visual Basic Editor)のイミディエイトウィンドウにて
? Obchk03Type
とコピペして、Enterします。
以下、コードです。これを好きな標準モジュールにコピペすれば使えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
' ' Function Obchk03Type() Dim ObjTest06 As Object Set ObjTest06 = Application.Selection Debug.Print TypeName(ObjTest06.Parent.Parent.Parent.Parent.Parent.Parent.Parent.Parent) Debug.Print TypeName(ObjTest06.Parent.Parent.Parent.Parent.Parent.Parent.Parent) Debug.Print TypeName(ObjTest06.Parent.Parent.Parent.Parent.Parent.Parent) Debug.Print TypeName(ObjTest06.Parent.Parent.Parent.Parent.Parent) Debug.Print TypeName(ObjTest06.Parent.Parent.Parent.Parent) Debug.Print TypeName(ObjTest06.Parent.Parent.Parent) Debug.Print TypeName(ObjTest06.Parent.Parent) Debug.Print TypeName(ObjTest06.Parent) Debug.Print TypeName(ObjTest06) Debug.Print "===============================" Stop Set ObjTest06 = Nothing End Function ' ' |
例えば任意のセルを選択してから、イミディエイトウィンドウにて「? Obchk03Type」と書いてEnterすると、以下のように表示されます。
Application
Application
Application
Application
Application
Application
Workbook
Worksheet
Range
===============================
これは・・・、
・「セル」というものは「Range」という種類の「オブジェクト」になりますよ~!
・そしてその上位には、「Application、Workbook、Worksheet」というオブジェクトがありますよ~!
・で、階層構造としては、以下のようになってますよ~、
Application
|_Workbook
|_Worksheet
|_Range
・階層構造の最上位は「Application」(=Excelのアプリケーションウィンドウ=親ウィンドウ)ですよ~!
・・・という意味になります。
(「Application」が複数出てきたら、2つめよりも上のものは無視します。)
そして、「Stop」命令のところで(Stopが黄色くなって)実行が一時中断しますので、その中断モードの状態で、「表示→ローカルウィンドウ」にて ローカルウィンドウを表示させると、そのオブジェクトの現在のプロパティ値を全部調べることができます。
ローカルウィンドウの中に「ObjTest06」という項目があると思います。それがシート画面上で選択したオブジェクトです。
そして、その項目の「+」マークをクリックすると、そのオブジェクトが持つすべてプロパティが表示されます。
展開された中の、
「式」の列がプロパティ名、
「値」の列が実際の各プロパティ現在の設定値
「型」がデータ型
です。
また、「Parent」という項目を探して「+」マークを展開して、段階的に「Parent」という項目ばっかりで探っていくと、親・ばあちゃん・ひいばあちゃん・・・、と上位のオブジェクトのプロパティ内容も全部わかります。
下位のオブジェクト(子、孫、)は、「Parent」以外の「+」マークの付いているものが全部それです。下位のオブジェクトも段階的にどんどん下へもぐれますので、何階層か下のオブジェクトのプロパティ値も知ることができます。
目的を達したら、F5キーを押せば、最後まで実行して何もしてない状態に戻ります。
※補足説明(超重要!!!)
厳密な階層構造としては、
Application
|_Workbook
|_Worksheet
|_Range
ではなくて、
Application
|_Workbooksコレクションオブジェクト
|_Workbook
|_Worksheetsコレクションオブジェクト
|_Worksheet
|_Range
・・・という風に、「コレクション(複数の同種・あるいは似た種類のオブジェクトたちを束ねて一括管理する機能を持つオブジェクト)」がそれぞれ所定の場所に存在する階層構造であると思います。
でも、オブジェクト式を書くときは、その「コレクションの階層」は出てこないので実際に書くことが無いですし、また、コレクション名自体も出てこないので、オブジェクト式を書く場合に限っては、便宜上、各コレクションオブジェクトの名前(階層)が省略された下図の階層構造図を使います。
Application
|_Workbook
|_Worksheet
|_Range
本自作関数(「Obchk03Type」)を使っただけではコレクションの位置づけがわかりませんが、「オブジェクト式を書くときだけ」、コレクションは単一オブジェクトと同じ階層だとみなして理解・記述します。(下図のようなイメージです。Excel2000のヘルプのオブジェクトモデルの階層構造図も同じような形になっています。←←※この図はよく使われるコレクションとオブジェクトしか載ってないらしく、描かれてないものもあります。例えばSheetsコレクションとかRangesコレクション。)
Application
|_Workbooksコレクション___ 単一のWorkbookオブジェクト
|_Worksheetsコレクション___ 単一のWorksheetオブジェクト
|_Rangesコレクション___ 単一のRangeオブジェクト
このことは・・・、
現実に実際にオブジェクト式を書くときに、
Application.Workbooks.Workbooks(1).Worksheets.Worksheets(1).Ranges.Range("A1")
と書くのではなく、
Application.Workbooks(1).Worksheets(1).Range("A1")
と書くことからも、
イメージできるのではないかと思います。
逆に、オブジェクト式を書く場合ではなく、例えば「エラー解決などをする際」は、
Application
|_Workbooksコレクションオブジェクト
|_Workbook
|_Worksheetsコレクションオブジェクト
|_Worksheet
|_Range
という感じで、コレクションの階層が「1段分」として増えた階層構造を念頭に置いて、エラー解決・原因調査、等々にあたります。
僕なんて特にそうなんですけど、どんなところ(どんな思い込みや決めつけ、勘違い、無知)に原因が潜んでいるかわかりませんので・・・。
※さらに補足(これも超重要!!!):プロパティ経由のオブジェクト取得とコレクション経由のオブジェクト取得(というか、同名のコレクションオブジェクト)を混同しないように。
なぜこのこのことが超重要かというと、そのことを知らないとExcelのヘルプが読めないからです。
Excelの場合、オブジェクト式に出てくる「いかにもコレクションっぽい名前」は、実はコレクション名ではなく、コレクション名と同名のプロパティの名前です(たとえばWorksheetsコレクションとWorksheetsプロパティ)。
同じ「s」が付いた複数形なので混同しやすいのですが、ヘルプにも、例えばWorksheetオブジェクトの場合なら、『単体の Worksheet オブジェクトを取得するには、Worksheets(index) プロパティを使用します。』とはっきりと書いてあります。
単体の Worksheet オブジェクトを取得するのに、「Worksheetsコレクションを使え」とは一切書いてありません。
なので、Excelでは、コレクションを直接使ってオブジェクトの取得をしているわけではないのです。(「コレクションの中から単一のオブジェクトを選び出す作業がなされている」というのは間違いないんですけど、それをコレクション自身が率先して・起点となってやっているわけではなくて、同じ名前のプロパティから頼まれてやってる・・・というイメージです。)
強いて言うと、Worksheets(index) プロパティを入り口として、裏方で目立たずにWorksheetsコレクション(本当はSheetsコレクションだけど)を覗きに行き、そこからWorksheetオブジェクトを1個、取得している・・・というイメージなのかもしれません。
あるいは、Worksheets(index) プロパティという「機能」が、「おーい!Worksheetsコレクションさーん!今から言うシートを1個、取り出してね~!」という感じでWorksheetsコレクションという「機能」に司令を伝達しているのかもしれません。私らド素人は謎の部分はそんな風に勝手にイメージしてもいいと思います。
「プロパティという機能が、自身でプロパティ設定をしつつ、同時にオブジェクトを連鎖取得もしている・・・」というばくっとしたイメージです。
なお、コレクション経由で・・・、つまり「コレクションから直接・コレクション起点で 単一のオブジェクトを取得するケース」というのは、例えば「コントロール」と呼ばれるオブジェクト(ユーザーフォーム上やシート上に作ったコマンドボタンやリストボックスなどの部品)を取得する場合がそうだと思います。
また、ExcelではなくAccessの場合はほとんどがコレクション経由です。プロパティ経由でオブジェクトを取得するケースは基本、ほとんど無いような気がします(って僕が知らないだけかもしれませんが・・・)。強いて言うとCOMオートメーションでExcelの機能を使う(=ExcelVBAをAccessVBAの中に書く)時くらいではないかと思います。
Wordの場合は、多分Excelと似て、プロパティ経由でのオブジェクト取得が多いと思います。
※2019/05/14 修正:この記事の「コレクション経由のオブジェクト取得ができる」という記述はすべて間違いでした。
大変申し訳ございませんでした。
本日別件でたまたまAccessのオブジェクトブラウザを見てみたら、すべて間違いとわかりました。
「大切な基礎の部分」で大ウソを流布してしまい、本当に申し訳ございませんでした。
穴があったり入りたいです。
「オブジェクト式」におけるAccessの「Forms」(つまり「Application.Forms」の「Forms」)は、「コレクション名」ではなくExcelの場合と同様、「プロパティ名」でした。
Accessのオブジェクトブラウザで確認できます。
Accessのオブジェクトブラウザで、Applicationを検索してオブジェクトのメンバを見ると、中に「Forms」というものがあり、すると、そのアイコンは「プロパティ」を表すアイコンです。
また、一番下の説明ペインにも「Property Forms As Forms」と書いてあります。
つまり、「プロパティのForms は、Forms というコレクションオブジェクトを返します。」という意味ですから、結果、「Application.Forms」の「Forms」は、コレクションではなくプロパティでした。
よってAccessでよく書く「Forms("フォーム1")」とか「Forms(1)」などの「Forms」は「コレクション名」ではなく「プロパティ名の「Forms」であった、ということです。
VBE上でFormsにカーソルを置いて、F1キーを押すとコレクションのことが出てきて、かつ、Excelのヘルプのように「 ××× オブジェクトを取得するには ××× プロパティを使います」と明示的に書いてないので誤解してしまいました。
今後は、オブジェクトブラウザから先に見るようにします。
ExcelやWordなどの「ユーザーフォーム」の各コントロール(テキストボックスやコマンドボタンなど)の場合も、これに同じです。
オブジェクトブラウザで調べると説明ペインに「Property ×××× As ×××× 」と書いてあります。
あと、なぜコレクションとプロパティの名前が同名になっているケースが多いのかはわかりませんが、そのほうが見た目的にわかりやすいからという単純な理由からかもしれません。真偽はマイクロソフトさんに聞いてください。
(02)すべての上位のオブジェクトの名前を一覧表示(「Obchk04Name」という自作関数)※Nameプロパティを持つオブジェクトだけ
多くのオブジェクトは、「Nameプロパティ」を保持していて、その設定値を調べられる仕組みになっています。
「Nameプロパティの設定値」とは、例えばユーザーがシートのタブで付けた名前とか、他方、ユーザーフォームや埋込グラフ、ピボットテーブル等々のように、Excelが自動的に各オブジェクトに付けてくれる名前とかです。
また、その「Nameプロパティ」の値は、オブジェクトの取得をするとき・・・つまり、「オブジェクト式」や「部分オブジェクト式」を書くとき・・・・によく使われます。
ここではその「Nameプロパティ」の値を、階層構造順にリストアップする関数をご紹介します。
こでもド素人が作ったのでショボいです。
ただ、こちらもStopでローカルウィンドウを使って、上位や下位のオブジェクトのプロパティを調べられる形にしてあります。(用が済んだらF5キーで終了してください)
なお、注意事項ですが、「Nameプロパティ」を保持していないオブジェクトもあるので、そういうものは空白行になるようになっています。(Rangeオブジェクトもその一つです)
標準モジュールにコピペして、イミディエイトウィンドウにて
? Obchk04Name
と書いてEnterして使ってください。
すると
Microsoft Excel
Microsoft Excel
Microsoft Excel
Microsoft Excel
Microsoft Excel
Microsoft Excel
Book11.xls
Sheet1
===============================
のように出ます。
空白行はNameを持ってないオブジェクトです。(例えばRangeオブジェクトなど)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
' ' Function Obchk04Name() Dim ObjTest07 As Object On Error GoTo error1: Set ObjTest07 = Application.Selection Debug.Print ObjTest07.Parent.Parent.Parent.Parent.Parent.Parent.Parent.Parent.Name Debug.Print ObjTest07.Parent.Parent.Parent.Parent.Parent.Parent.Parent.Name Debug.Print ObjTest07.Parent.Parent.Parent.Parent.Parent.Parent.Name Debug.Print ObjTest07.Parent.Parent.Parent.Parent.Parent.Name Debug.Print ObjTest07.Parent.Parent.Parent.Parent.Name Debug.Print ObjTest07.Parent.Parent.Parent.Name Debug.Print ObjTest07.Parent.Parent.Name Debug.Print ObjTest07.Parent.Name Debug.Print ObjTest07.Name Debug.Print "===============================" Stop Set ObjTest07 = Nothing Exit Function error1: Debug.Print "" Resume Next End Function ' ' |
(03)すべての上位のオブジェクトのインデックス番号を一覧表示(「Obchk05Index」という自作関数)※Indexプロパティを持つオブジェクトだけ
「オブジェクト式」や「部分オブジェクト式」を書くときに、「Nameプロパティ」が使えずに、「Indexプロパティ(インデックス番号)」しか使えないオブジェクトがあります。
これはそういうオブジェクトのインデックス番号番号を階層構造込みで、調べるものです。
また、「Indexプロパティ」を保持していないオブジェクトはとても多いので、かなりの行が空白行になります。
例えば、イミディエイトウィンドウで「? Obchk05Index」と書いてEnterすると、以下のように空白がたくさん表示されます。でも数字が出れば何かの役に立つことも少なくないので、それはそれでありがたく使わせてもらいます。
? Obchk05Index
2
===============================
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
' ' Function Obchk05Index() Dim ObjTest08 As Object On Error GoTo error1: Set ObjTest08 = Application.Selection Debug.Print ObjTest08.Parent.Parent.Parent.Parent.Parent.Parent.Parent.Parent.Index Debug.Print ObjTest08.Parent.Parent.Parent.Parent.Parent.Parent.Parent.Index Debug.Print ObjTest08.Parent.Parent.Parent.Parent.Parent.Parent.Index Debug.Print ObjTest08.Parent.Parent.Parent.Parent.Parent.Index Debug.Print ObjTest08.Parent.Parent.Parent.Parent.Index Debug.Print ObjTest08.Parent.Parent.Parent.Index Debug.Print ObjTest08.Parent.Parent.Index Debug.Print ObjTest08.Parent.Index Debug.Print ObjTest08.Index Debug.Print "===============================" Stop Set ObjTest08 = Nothing Exit Function error1: Debug.Print "" Resume Next End Function ' ' |
(04)色の数値を「赤・緑・青」の数値に変換する(「GetIntByRGB」という自作関数)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
' ' Function GetIntByRGB(ColoerNum As Variant) Dim Red As Variant Dim Green As Variant Dim Blue As Variant Red = ColoerNum Mod 256 Green = Int(ColoerNum / 256) Mod 256 Blue = Int(ColoerNum / 256 / 256) Debug.Print "赤=" & Red Debug.Print "緑=" & Green Debug.Print "青=" & Blue End Function ' ' |