★独学者が1年後にExcelVBAを爆発的に伸ばすための最低限の基礎知識メモ(ダイジェスト):Vol0006:オブジェクト取得方法と挫折しないための「コレクションとは?」
  
バックナンバー目次ページは→こちらです。

まぐまぐのページは以下です。
https://www.mag2.com/m/0001691660.html
  
  
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
■独学者が1年後にExcelVBAを爆発的に上達させるための最低限の基礎知識メモ(ダイジェスト)

Vol.0006

タイトル:オブジェクト取得方法と挫折しないための「コレクションとは?」
  
  
バックナンバー目次とサンプル号
https://euc-access-excel-db.com/tips/ct07_se/ct075012_xls2k_vba_tips/mag2-01

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

またもや前号、前々号での記述ミスを発見してしまいました。

あまりに多くてすみません。

多いので、今後は、ここではなくて、ホームページのバックナンバー側で随時、訂正や加筆をいたします。

https://euc-access-excel-db.com/tips/ct07_se/ct075012_xls2k_vba_tips/mag2-01

↑こちらから、各号を、ちょくちょく、読み直してみてください。

本当にご迷惑をおかけしてすみませんが、よろしくお願い致します。
(そもそも私はExcelもExelVBAも初心者なので、完全には直せないかもしれません。
 そのときは、本当にすみません。)

では、以降、今回分の本文です。
  

==================
  
  

★ (08)「オブジェクトを取得する方法」とは?

オブジェクトの取得、とは、操作対象のオブジェクトを一つに決める、ひとつ選択する、というイメージです。

で、その、オブジェクトを取得する=選択する方法には、以下のような方法があります。
  

(a)プロパティから、コレクション+Itemプロパティ経由、などで。(下位、上位)
(b)メソッドから、コレクション+Itemプロパティ経由や、その他(AddやOpenなど)で。
(c)関数で。CreateObject関数やGetObject関数など。
(d)Office全体(MSO××.DLL)のオブジェクトに属するプロパティやメソッドで。
(e)イベントプロシージャの引数からオブジェクトをGET。
(f)(a)の補足ですが、単一オブジェクトの、各種の「プロパティ」を使う。
(g)(b)の補足ですが、単一オブジェクトの、各種の「メソッド」を使う。

以降で、少し補足説明をさせて頂きます。

  

※参考図
例えば Rangeオブジェクトの取得の場合、どういったプロパティなどが使われるか、の「イメージ」の図です。
あくまでも「イメージ」ですが、下図の「正規ルート」と「ワープルート」の違いなどを良く見てみてください。
「正規ルート」では普通の原則的なセル範囲(A1形式のセル範囲)が取得でき、
「ワープルート」では、「少し便利なかたち(性格が異なったかたち。R1C1形式や使用された部分のみ等々)でのセル範囲が取得できます。
(※「ワープルート」=下の図で言うと、オレンジの点線矢印でのRangeオブジェクトのゲット=アクセスのルートのことです。)

※各コレクションオブジェクトの「Item」という名前のプロパティやメソッドは基本、省略されることがほとんどです。(後述)
ただ、「VBAは省略しない方が上達します」。
あと、一口に、例えば「Cells」プロパティと言っても、Application.Cellsもあれば、Worksheet.CellsやRange.Cellsもあって、「それぞれに「微妙に動きが異なる」ので、「親となるオブジェクトとセットで」、「どのCells」オブジェクトなのか、を明確に指定する必要があります。それは「Cells」に限らず、他のプロパティでも同じことが言えます。
(例えば上図だと「Application.Selection」や「Window.Selection」、各種「Item」がそれにあたります。)
なので上図では、その意味で、「親となるオブジェクト」の名前もくっつけた状態で説明してあります。
「ヘルプ(特に2007以降)」や「オブジェクトブラウザ」もこの形式を守っていますので、逆に、このことを知らないと、「ヘルプ」や「オブジェクトブラウザ」が読めません。
ご注意ください。
  

では以降、(a)~(g)の説明です。

(a)プロパティから、コレクション+Itemプロパティ経由、などで。(下位、上位)
※基本的に、下位の階層にコレクションが居る場合は、プロパティでもメソッドでもコレクションを取得します。コレクションが居ない場合は、単一オブジェクトが「直で」取得されます。
  
※下図もご参考にしてみてください。イエローがコレクションオブジェクトで水色が単一のオブジェクトです。
コレクションが居るところは、コレクションと単一オブジェクトのセットで1階層分です(WorkbookやWorksheetのところとか)。
コレクションが居ないところは、単一オブジェクトだけで1階層分です(例えば「Range」のところとか)。
コレクションが居る・いない、は、全体からすると半々くらいです。コレクションが居ないケースが意外と多いです。(Rangeは基本的には単一なのに、コレクションの性格も併せ持つ特殊なオブジェクトです)


以下、上の図のもう少し広範囲なPDFです(すべてではありませんが)。
拡大表示して見てみてください。
https://euc-access-excel-db.com/00000WPPDF/object-model01.pdf
  

そして、そのコレクションが、自分が内包しているItemプロパティかItemメソッドで、
右ヨコに居る「単一のオブジェクト」を最終的に、ゲット=取得してくれることが多いです。
(例外があるかも?)

でも一方で、「同じ階層にコレクションが同居していない単一オブジェクト」もあるので、
(繰り返しになりますが)その場合はプロパティ直で単一オブジェクトが取得されます。
例えば、
「Range.Font プロパティ」や
「Workbook.Range プロパティ」
「Workbook.Names プロパティ」
「Worksheet.Names プロパティ」
などです。
これらのプロパティは、下位の同名の単一オブジェクトを、直接、ゲットしてくれます。
「Item」は使いません。(そもそも対になるコレクションオブジェクトが存在しないため、Item、自体が、無いのです。)
  

(b)メソッドから、コレクション+Itemプロパティ経由や、その他(AddやOpenなど)で。

プロパティの場合と同じ動きです。
  

(c)関数で。CreateObject関数やGetObject関数など。
(VBE6.DLL、あるいはVBA7.DLLなど)に属する関数)
  

(d)Office全体(MSO××.DLL)のオブジェクトに属するプロパティやメソッドで。
「CommandBar.Controls プロパティ」(?)などです。
  

(e)イベントプロシージャの引数からオブジェクトをGET。
(例えば、Worksheet.SelectionChangeイベントなどの引数の「Target」、など)
  

(f)(a)の補足ですが、単一オブジェクトの、各種の「プロパティ」を使う。
基本、「プロパティ」は、『 オブジェクトの性質を決める各種設定の設定値を読んだり書き換えたりするもの 』がメインですが、それとは別に、「オブジェクトを取得することだけに特化したプロパティ」も結構たくさん存在します。
それには、「下位のオブジェクトを取得するもの」や、「上位のオブジェクトを取得するもの」があります。
「Item」以外のプロパティの話の補足です。
下位のオブジェクトを取得するモノは、例えば「Workbook」という単一オブジェクトでなら、
「Workbook.Names プロパティ」
「Workbook.Sheets プロパティ」
「Workbook.Styles プロパティ」
「Workbook.Worksheets プロパティ」
などがあります。

下位のオブジェクトを取得するプロパティについては、
下位の階層に単一のオブジェクトしかない場合はそれを直接、
対になるコレクションオブジェクトも在る場合は、単一のモノの取得よりも先にそれを、
取得するかたちになります。
(上記のプロパティはすべて「先にコレクションを取得するパターン」です。)
  

また、上位のオブジェクトを取得するモノは、「Parentプロパティ」で取得することが多いかも?です。

「Parentプロパティ」は、
「×××.Parent」と書くと1階層上位の単一オブジェクトをゲット(取得)し、
「×××.Parent.Parent」と書くと2階層上位の単一オブジェクトを、
「×××.Parent.Parent.Parent」と書くと3階層上位の単一オブジェクトを・・・、
といった具合に、複数連ねて使うことで、何階層でも上の単一オブジェクトをゲット(取得)することができます。
  

そのほか、
「Worksheet.Application プロパティ」とか、
「Range.Worksheet プロパティ」、
「QueryTable.ListObject プロパティ」(も?)
・・・といった感じで、そのようなプロパティでも上位のオブジェクトを取得できます。

Parentは、「1階層上=親オブジェクト」しか取得できませんが、Application プロパティなどは、数段階層をすっとばして、最上階層のオブジェクトを取得できます。
Application プロパティは、特に、WordやAccess、PowerPointやOutlookなどと「COMオートメーション」で連携するときなどに、ちょいちょい使用します。

上位のオブジェクトを取得できるメリットは、上位のオブジェクトの機能(プロパティやメソッド)を、新たにオブジェクト変数を使う(=作る)ことなく、「ちょい利用」「つまみ食い利用」できるので、コード量を少し減らすことができ、読みやすくなったり・便利になる点です。
これが、『 オブジェクトの持つ、階層自由往来機能、というか、上下階層の機能の流用機能 』・・・、です。
ここでは特に上位のオブジェクトに対することについて書きましたが、もちろん、下位のオブジェクトに対してもそうです。
すべてのオブジェクトは、単一ものものもコレクションも、オブジェクトモデルとして、階層をなして紐付き合っていますので、その紐をたどっていけば、上の階層でも下の階層でも、新しくオブジェクト変数を設置(作る)ことなく、それらのオブジェクトの「ちょい」「機能のつまみ食い」、が可能です。

※「COMオートメーション」とは?
ExcelVBAからAccessVBAのコードを書いて動かしたり、その逆、あるいは、WordVBAからQutlookVBAのコードを書いて動かしたり・・・、ということができる、そういう機能です。
オートメーションに対応したソフトなら、Officeのソフトだけでなく、例えばFileMakerなどの他社のソフトも連携操作することができます。
  

(g)(b)の補足ですが、単一オブジェクトの、各種の「メソッド」を使う。
基本的にはプロパティの場合と同じ動きをします。
「Item」以外のメソッドの話の補足です。

具体例としては、例えば「Worksheet」という単一のオブジェクトの場合、
「Worksheet.ChartObjects メソッド」
「Worksheet.PivotTables メソッド」
などがあります。

下位の単一オブジェクトを取得するメソッドの数は、プロパティのほうが数としては圧倒的に多いです。また、上位のオブジェクトを取得するメソッドはほとんど無いかもしれません。(確認したことはありませんが)

なお、メソッドもプロパティの場合と同様、
下位のオブジェクトを取得するメソッドについては、
下位の階層に単一のオブジェクトしかない場合はそれを、
コレクションオブジェクトも在る場合はそれを、
取得するかたちになります。
  
  

※プロパティもメソッドも、下位の階層にコレクションオブジェクトが同居している場合は、単一のオブジェクトを「直で」取得するわけではなく、コレクションオブジェクトが先に取得されます。その後、コレクションオブジェクトに含まれる「Item」という名前のプロパティかメソッドが、コレクションと同じ階層に同居する単一のオブジェクトを取得します。
複数の単一オブジェクトが居れば、名前やインデックス番号で1つに特定、ゲットしてくれます。
  
  
  

##############################
##############################

  
  
  

★ (09)挫折しないための「コレクション」とは?

コレクションとは、複数の「単一のオブジェクトたち」を管理するオブジェクトです。
「単一オブジェクトを単発操作あるいは一括操作する装置」とか、
「単一オブジェクト・単複両管理装置」などと言ってもいいかもしれません。
  

基本、ワークシート、ブック、グラフシート、オートシェイプ、などの、「複数・新規作成ができる単一オブジェクト」はすべて(?だと思います)、コレクションオブジェクトによって管理されています。

なので、そういう単一のオブジェクトには、それぞれに、対となるコレクションオブジェクトが存在します。
  

逆に、FontオブジェクトやInteriorオブジェクト、Sortオブジェクト、AutoFilterオブジェクト、など、「複数・新規作成でき ” ない ” 単一オブジェクト」には、コレクションオブジェクトは存在しません。
(※目に見える・見えない・大きい・小さいに関係なく、「設定機能や動作機能の集まりなだけ」のような、そもそも新規作成する必要が無いオブジェクト等の場合は、対になるコレクションオブジェクトは存在しません。
ただし、例えばAutoFilterオブジェクトの場合、その中(1階層下)には、複数の「フィルタ条件」を「新規作成」できるので、そのような場合は「AutoFilter.Filters」のようにコレクションが存在します。
「コレクションが存在しないオブジェクトは、その中(下の階層)のオブジェクトまでも全部が全部、同じようにコレクションが存在しない」というわけでは「ありません」ので、そこは誤解のないようにご注意ください。)

  
※下図もご参考にしてみてください。イエローがコレクションオブジェクトで水色が単一のオブジェクトです。


以下、上の図のもう少し広範囲なPDFです(すべてではありませんが)。
拡大表示して見てみてください。
https://euc-access-excel-db.com/00000WPPDF/object-model01.pdf
  
  
※補足
コレクションオブジェクトが単一オブジェクトと同じ階層に同居する(=単一オブジェクトの左側に位置する)図は、ADOやDAOのオブジェクトモデルにも描かれています。なので、Excel本体の場合もそのように理解しても、あながち「まちがい」と断定せずとも良いと考えています。
むしろ、Excel本体もそう考えたほうが「ヘルプやオブジェクトブラウザ」が扱いやすくなります。
(以下、Excel2000のヘルプより)


  
  

そして
  
「コレクションオブジェクト」も、「単一のオブジェクト」とともに、「オブジェクト」のひとつ、

です。

といいますか、これまで述べてきましたとおり、「オブジェクト」は大別すると
・「単一のオブジェクト」と
・「コレクションオブジェクト(通称コレクション)」の
2つしかありません。

また、両方とも「階層構造(オブジェクトモデル)」に組み込まれています。
(※上図参照)

  
  
★ コレクションは「配列」っぽい?
コレクションを使うと、「単一オブジェクト」を名前やインデックス番号で指定できます。
そのため、配列を使う時のように、単一オブジェクトを「一括処理」できるので便利です。
(※「名前」は、NameプロパティとCodeNameプロパティがありますが、コレクションオブジェクトから使えるのはNameプロパティのほうです。)

※「配列」についてまだ学んでおられない方は、先に配列について学んでみてください。

  
  
★ 「コレクション」の階層構造(オブジェクトモデル)の中での居場所

繰り返しになりますが、コレクションオブジェクトは(1つの階層の中において)、単一オブジェクトと対になっている場合と、コレクションオブジェクト自体が存在しない場合があります。

前述・上図のオブジェクトモデル(階層構造)の拡大図のPDFを見るとわかりますが、例えば・・・、
・ワークシートの中のRangeオブジェクトや、
・Rangeオブジェクトの中の「Fontオブジェクト」「Interiorオブジェクト」「Styleオブジェクト」「Commentオブジェクト」、
などは、
「対となるコレクションが存在しない」・・・というケースです。
そして、その階層はそういう風に「コレクションが無い階層」でもあります。

それらの単一オブジェクトでは、対となるコレクションオブジェクトは存在しないので、コレクションの位置など気にしなくてもいいですが、それに対して、WorkSheet、Chart、Workbook、Shape、等々のオブジェクトにはコレクションオブジェクトが存在します(同じ階層に)。

その場合のコレクションオブジェクトの位置は、(上図のように)、
・「単一オブジェクトの左側に居る」
・単一オブジェクトと同じフロア、同じ階層、に「同居」している
とイメージするとよいと思います。
(前項の図もご参考にしてみてください。)

もしかしたら理解し間違えているかもしれませんが、初心者のうちはそれでも問題ないと思います。

中級になってからでも特別に難しいプログラムを作るのでなければ、そのような理解で、しばらくは大丈夫だと思います。

「Sheets」コレクションオブジェクトのように、どこに位置するか明確に描き表せないコレクションオブジェクトもありますが、良く使うコレクションオブジェクトについては、ほとんどは「単一オブジェクトの左側に位置している・・・と理解してよいと思います。

ちなみにですが、「Sheets」コレクションオブジェクトは、WorksheetsとかCharts、といったコレクション達と同じフロア、同じ階層、に「同居」しているイメージです。
(というか、それらのコレクションと一緒のフロア・・・・、ということは、結局、WorksheetやChartといった単一のオブジェクトとも同じフロアに居る・・・、ということなんですけれども。そういうイメージです。)

  
  
★ コレクションオブジェクトの主な機能

そして「コレクション」は、主に、以下の3つの機能を持っています。
(=「一括処理」しかしないわけではありません。)
  
(a)自分自身が内包している「Item」プロパティ・あるいは・「Item」メソッドを使って、「自分の右ヨコに居る」単一オブジェクトを個別に選びだす機能。(単一オブジェクトを特定してユーザー側に返す機能)
※コレクションオブジェクトたちは単一オブジェクトたちのように、「下位の階層のオブジェクトを取得する」という機能は基本的には持っていません。例外はあるかもしれませんが。ただ、逆に「1階層上位」の単一オブジェクトを取得できる「Parentプロパティ」は持っていますけど・・・。

(b)同じ種類の複数の単一オブジェクトたちをごそっと束ねて、削除したり、コピーしたり、閉じたり、印刷したり、といった、「一括処理」をする機能。

(c)単一オブジェクトを個別に開いたり、新規作成したり、削除したり、コピーしたり、などの動作をする機能。
(※「個々の単一オブジェクト単独の」削除やコピー、印刷等々は、「Itemで選び出された単一オブジェクトのほうに紐ついた命令」でしかできないことであり、コレクションではできない動作でした。誤りでした。すみません。コレクションでできるのは、「複数一括削除」や「複数一括コピー」だけでした。ただ、単独で「開いたり、新規作成したり」はコレクションの役目です。)
  
  
※(b)の『 ごそっと「一括処理」する機能 』は、メソッドで行うことが多いのですが、メソッドで処理することができない・でも・ゴソっと一括処理したい、という場合は、
・コレクション+Itemのインデックス番号+For Next ループ文など、あるいは、
・For Each 文、
等々を使うと、『 ごそっと「一括処理」する 』ことができます。
(ただし、この場合は、コレクションのメソッドを使うのではなく、単一オブジェクトのほうのメソッド等々を使うことになるのですが)
なお「For Each 文」は配列とコレクションに対してのみ、使えます。
  
  
それぞれを少し補足説明すると以下のようになります。
  

(a)「Item」プロパティか「Item」メソッドを使って、単一オブジェクトを個別に選びだす機能。(単一オブジェクトを特定してユーザー側に返す機能)

基本、コレクションはどのコレクションでも、「Item」という名前のプロパティかメソッドを持っています。

「Item」は、それがプロパティであってもメソッドであっても、

・複数の単一オブジェクトたちの中から、
・ユーザーが指定したインデックス番号か名前で1つの単一オブジェクトを選び出す

という機能を有しています。
(※繰り返しますが、単一オブジェクトたちは、コレクションと同じ階層の「右ヨコ」に居るイメージです。)
  

ただ、同じような機能なのに、なぜ、プロパティとメソッドに分かれているのかは、
当方にはわかりません。

当面は『 マイクロソフトさんが決めた「仕様」』と理解してしまってもいいと思います。
でも、いつか、その区別をしないといけない時が来るかもしれません。
そのときは是非、有名なレジェンドさんたち、あるいは講師さんたちに聞いてみてください。

なお(注意事項としてですが)、例えばワークシートを取得するためのオブジェクト式を
ActiveWorkbook.Worksheets("Sheet1")
と書いてしまうと、
あたかも「Workbook 単一オブジェクト(ここではActiveWorkbookプロパティがゲットしているモノ)」が内包している「Worksheetsプロパティ」が、
「Sheet1」という名前の単一のワークシートを「直接」取得しているように誤解しやすいですが、そうではありません。

ActiveWorkbook.Worksheets("Sheet1")
は、
本当なら、
ActiveWorkbook.Worksheets.Item("Sheet1")
というように「Item」が省略されて書かれているにすぎないので、
実際には、「 Workbooks  Worksheetsコレクションオブジェクト」が内包している「Itemプロパティ」
という命令が、
「Sheet1」という単一のシートを取得(ゲット)しています。

それに対して、
「Workbook 単一オブジェクト」が内包している「Worksheetsプロパティ」のほうは、
(Itemプロパティを所有・内包している)「Workbooksコレクションオブジェクト」「だけ」をゲットしているだけなのです。
↓こちらの図も参考にしてみてください。
(Ctrlキーを押しながらマウスホイールを回すと拡大して文字がよめるようになります)
https://euc-access-excel-db.com/00000WPPDF/get-object-basic02-disc-cut.pdfや、
https://euc-access-excel-db.com/00000WPPDF/get-object-basic01.pdf

※★★ 超重要!!
 「Workbook 単一オブジェクト」が内包している「Worksheetsプロパティ」・・・
 という意味のことを、
 「Workbook.Worksheetsプロパティ」とドットを挟んで表現することがあります。
 「Workbook 単一オブジェクト」が「Worksheetsプロパティ」の「親」に位置する、
 という感じの表現方法です。
 ヘルプに多い表現方法ですので、必須の表現方法です。

 ヘルプでのプロパティやメソッドの検索は、このように親に位置する単一オブジェクトを
 頭にくっつけて検索するのが鉄則です。Web検索するときも有効です。
 ただこれは、2007と2010のヘルプでは守られていますが、
 2013以降のヘルプでは退化して守られていません。
 というか、2013以降のヘルプでは何かを検索しても
 まともにヒットしないことすらあります。
 ブラウザが起動しても真っ白なまま、とか。
 (意味がわかりません。
  マイクロソフトのエンドユーザー軽視、特に「個人ユーザー軽視」、
  ここに極まれり!、という感じです。
  といいますか、ここまでくると怒りを通り越して、
  「お見事!」
  「さすが!」
  「だよね!」
  「やっぱりマイクロソフトはこうでなくっちゃ!」
  と、ただただ、感嘆するばかりです。)
  
  

話が逸れてすみません。モトに戻します。
  

つまり、

ActiveWorkbook.Worksheets("Sheet1")
は、
ActiveWorkbook.Worksheets.Item("Sheet1")
と書くのが「本当」で、
訳し方の例としては、

『アクティブなブックの中の、
 Worksheetsコレクションオブジェクトの中の、
 (その中の)Itemプロパティがゲットしてくれているワークシートの「Sheet1」』

という感じで訳します。

※「ActiveWorkbook.Worksheets.Item("Sheet1")」は、実は本当は、さらに
「Application.ActiveWorkbook.Worksheets.Item("Sheet1")」と、
先頭に「Application.」も付けて、
書くのが本当です。
(さらには、「Excel.Application.・・・」と「Excel」を付ける場合もあります。特にWordやAccessをCOMオートメーションなどで同時起動させている場合)
  

同じように、
Workbooks("Book1.xlsx").Worksheets("Sheet1")
は、例えば
Application.Workbooks.Item("Book1.xlsx").Worksheets.Item("Sheet1")
と書くのが本当で、
訳し方の例としては、

『(Excel)Application単一オブジェクト の、
 1階層下に位置する「Workbooks」コレクションオブジェクト の中に居る、
 「Itemプロパティ」がゲットしてくれている単一のブックの「Book1.xlsx」の、
 さらに1階層下に位置する「Worksheets」コレクションオブジェクト の中に居る、
 「Itemプロパティ」がゲットしてくれている単一のワークシートの「Sheet1」』

という感じになります。
  

また、少し違う(超めんどくさい)言い方をすると・・・

『Application という単一オブジェクトに含まれる
 「Workbooks プロパティ」という命令が、

 1階層下に位置する「Workbooksコレクションオブジェクト」をゲットし、
 その「Workbooksコレクションオブジェクト」の中に含まれる
 「Itemプロパティ」という命令が

 「Workbooksコレクションオブジェクト」の
  右側(同階層)に居る単一のWorkbookオブジェクトの「Book1.xlsx」をゲットし、
 さらにその単一のWorkbookオブジェクトに含まれる
 「WorkSheets プロパティ」という命令が、

 さらに1階層下に位置する「Sheetsコレクションオブジェクト 」をゲットし、
 さらにその「Sheetsコレクションオブジェクト」の中に含まれる
 「Itemプロパティ」という命令がゲットしてくれている、

 (Sheetsコレクションと同じ階層に居る)
 単一のWorkSheetオブジェクトの「Sheet1」』

という感じにもなります。
(下図の階層、コレクションの位置関係もご参考にしてみてください。
 ※「Sheetsコレクションオブジェクトは描かれていませんがWorkSheetsコレクションの近くに居る、とでもイメージしてください。)

(※コレクションと単一オブジェクトは同じ階層に「同居」しています。https://euc-access-excel-db.com/00000WPPDF/object-model01.pdf を拡大表示して見てみてください。https://euc-access-excel-db.com/00000WPPDF/get-object-basic02-disc-cut.pdf
https://euc-access-excel-db.com/00000WPPDF/get-object-basic01.pdfも拡大表示してご参考にしてください。)
  

※なお、「Workbook.WorkSheets プロパティ」は、「WorkSheets コレクションオブジェクトを取得する」と思いがちですが、実は(?)そうではなく、「Sheetsコレクションオブジェクト」を取得します。

「Sheetsコレクションオブジェクト」はワークシートやグラフシート、その他のシートを束ねて単独&一括管理しているコレクションオブジェクトです。

WoksheetsコレクションとChartsコレクションを足したような機能を有しています。
ワークシートやグラフシートの垣根を超えて、「すべてのシートに何らかの処理を施したい時」などに、プログラムが短く書けることになるので便利になると思います。

上記のオブジェクトモデルの図には描かれていませんが、「Worksheetsコレクションオブジェクトの更に左とか、あるいは、単一オブジェクトの左側あたりに同居している・・・みたいにイメージしてみてください。

ただ、Sheetsコレクションを取得すると言っても、
例えば何らかのグラフシートを作ったのちにイミディエイトウィンドウで、

? ActiveWorkbook.Worksheets("Graph1").Name

とグラフシートを指定して名前を調べようとしてもエラーになってしまいます。

? Typename(ActiveWorkbook.Worksheets)
とやると
Sheets
と返ってくるし、
? ActiveWorkbook.Sheets("Graph1").Name
とやると
Graph1
って返ってくるので、もしかして
? ActiveWorkbook.Worksheets("Graph1").Name
とやると
Graph1
って返ってくるのかな~?と思いきや、
エラーになってしまうので、「???なんで???」ってなります。(^^)

あたりまえのような気もしますし、なんだかスッキリしない面もあると思います。

僕にはわからないので、是非、レジェンドの方や講師の方に聞いてみてください。

なお、このように「そういうことなら、こういうこともできるのかな?」と試すことは非常に重要です。

それがある人は・・・、それを持っている人は・・・、
「ある地点から爆発的に伸びる素養がすごくある!」と思います。

話が逸れましてすみません。

Sheetsコレクションは、2000のヘルプやマイクロソフトのサイトの一覧図にも描かれていません。
でも、階層構造としては、Woksheetsコレクション・Chartsコレクション・Worksheet単一オブジェクト・Chart単一オブジェクトと同じフロアに同居していることになっています。

イミディエイトで、「? TypeName(Sheets.Parent)」でEnterすると、「Workbook」と返ってきます。
これは、「? TypeName(WorkSheets.Parent)」でも「? TypeName(Charts.Parent)」でも、同様に「Workbook」と返ってきます。

「××.Parent プロパティ」は「1階層」「上位」のオブジェクトを調べたり、「1階層上位」のオブジェクトの機能を流用したりするときなどに使うプロパティです。
(「1階層上位」、と書いてある場合、基本、「単一の」、上位のオブジェクトの事を意味します。)

それによって、同じ「Workbook」答えが返ってくる・・・、ということは、
「1階層上のオブジェクトがみな同じ」ということでして・・・、
ひるがえせば、みな、同じフロアに同居している、という証明となります。

「? Sheets.Parent.Name」
「? WorkSheets.Parent.Name」
「? Charts.Parent.Name」
でやると、もっと分かりやすいかもしれません。
全部、同一のブックの名前が返ってきますので。

  

非常に面倒くさい言い回しですが、でも、こんな感じのことが理解できないと、ヘルプとオブジェクトブラウザが読めません。

逆に言うと、
https://euc-access-excel-db.com/00000WPPDF/object-model01.pdf を拡大表示して見てみながら、階層をたどりながら、
このような面倒~くさい言い方ができるようになって、「返す」の意味がわかると、
・ヘルプとオブジェクトブラウザが「突如、堰を切ったようにスラスラ読めるようになるひと」
もいらっしゃいます。

  
  
  

(b)同じ種類の複数の単一オブジェクトたちを束ねて、一括「処理」する機能。

一括で閉じる(Close)、一括印刷(PrintOut)、一括コピー(Copy)、
一括で削除(Delete)、など。
  
  
  

(c)単一オブジェクトを個別に開いたり、新規作成したり、削除したり、などの動作をする機能。

単一オブジェクトを新規作成(Add)、既存の単一オブジェクトを個別に削除(Delete)、開く(Open)、コピー(Copy)、など。
その際の、Add、Openなどの一部のメソッドは、GetObjectやCreateObject関数と同じように、
そのような「新規作成」「開く」といった動作をしつつ、同時に、
『 ついでに、オブジェクトもユーザー側に投げ返して 』もくれます。
(投げ返されたオブジェクトを取得して変数に代入することができます。
また、その際の記述には カッコが必要です。)

※「Close」「PrintOut」「Delete」「Copy」などは、
  『 単一処理にも複数一括処理にも「使える」、そういう命令・・・』、
  ということになります。

※↑これは誤りでした。すみません。
「コレクションの場合に限って」言えば、「Close」「PrintOut」「Delete」「Copy」などは、「複数一括処理」に「だけ」しかた「使えない」命令でした。
単一処理での「Close」「PrintOut」「Delete」「Copy」などは、単一のオブジェクトの側でしかできない処理でした。すみませんでした。

  
  

※基本、「コレクション」は、
それ自体が「単一のオブジェクトたちを束ねて個別管理や一括管理をする」
という側面を持っているため、
多くのコレクションでは、それぞれが似たようなプロパティやメソッド(=似たような命令)を保持・保有・内包しています。

例えば「Application、Count、Creator、Item、Add、Open、Delete」、などが、その似通ったプロパティやメソッドです。そこそこ多くのコレクションオブジェクトが、これらの命令を内包しています。

また、単一のオブジェクトよりもプロパティやメソッドの数が少ないケース(数個から十数個)がほとんどです。
(オブジェクトブラウザで調べると(かつ、逆に言うと)、
 「Item」を持っていて、プロパティやメソッドの数が少ないものは確実に「コレクション」だ、
という判断ができます。
 オブジェクトブラウザで「Item」で完全一致で調べるとわかります。
 また、そこでそれぞれのコレクションの、プロパティやメソッドの個数も、
 調べることができます。)
  

「コレクションオブジェクト」において、もっとも大切・かつ・初心者本が説明しないコトは、

『 コレクションは、必ず「Item」という名前のプロパティ・または・メソッドを持っている 』、

ということと、プラス、

『 コレクションもオブジェクトの一種で、「階層構造に組み込まれている」』
『そして、コレクションは単一のオブジェクトの上位ではない』
『単一オブジェクトの上位に位置するものは、単一オブジェクトのみ』
『じゃあコレクションは、いったいどこに位置するのか?』

ということです。
  

そして、「オブジェクトを取得するプロパティやメソッドたち」の動作のなかで、真にオブジェクトをユーザー側に返しているのは、
『 この「Item」という名前のプロパティ・または・メソッド であることが多い 』ということもです。
  
  

「Item」は、「単一のオブジェクトを取ってこい!そしてこっちに投げてよこせ!」という意味の命令です。

これはプロパティでもメソッドでも同じです。

コレクションオブジェクトの中に属する単一のオブジェクトを、ユーザーが指定した名前かインデックス番号で、ゲットしてくれます。
  

もちろん、「オブジェクトを取得するプロパティやメソッドたち」の全部が全部、そういう動きをするわけではありません。

「××.Application プロパティ」、
「Range.Worksheet プロパティ」、
「Range.Offset プロパティ」、
「××.Open メソッド」、
「××.Add メソッド」、などのように、
そういう動きをしない「でもオブジェクトを返す・オブジェクトをゲットしてくれる」、プロパティやメソッドもあります。(一部、コレクションとは関係はありませんが。)

でも、そういったものよりも、「Item」でオブジェクトをゲットしてくれるパターンのほうが
明らかに「多い」のです。
  

このことを教えてもらえないことも、初心者の方々を簡単に挫折させてしまう「諸悪の根源のひとつ」です。
  

逆に言うと、基本、「Itemプロパティ又はItemメソッド」を持っているオブジェクトは「コレクションオブジェクト」です。
(Worksheet.Rangeプロパティなどだけはちょっと違う感じですが)
繰り返しになりますが、オブジェクトブラウザでも、Itemで完全一致で検索すると、コレクションがずらずらずら~っと出てきます。

また、コレクションオブジェクトは、
・単一オブジェクトの「上位には位置しない」・・・
と考えたほうがよさそうです。

「単一オブジェクトと同じ階層・フロア・真ヨコに居る」と考えたほうがよさそうです。
それで、ヘルプとオブジェクトブラウザは読めます。

※実際、ADOなどのヘルプのオブジェクトモデル一覧図は、そう描かれています。
 https://euc-access-excel-db.com/00000WPIMG/2018-09-02---00-39-58.jpg
 https://euc-access-excel-db.com/00000WPIMG/2018-09-02---00-46-25.jpg
 下のツリー状の図ような感じです。
 1階層あたりに、コレクションと単一のオブジェクトがヨコに並びます。
 もちろん、上位のオブジェクトにも、多くは、その左側にコレクションが居ます。
 (一部、コレクションが居ない単一オブジェクトもありますけど。
  Excel2000から2003のヘルプの一覧図で確認すると早いです。
  https://euc-access-excel-db.com/00000WPPDF/object-model01.pdf
  をご参照ください。)
  

  『 コレクションもオブジェクトの一種で、「階層構造に組み込まれている」』
  『そして、コレクションは単一のオブジェクトの上位ではない』
  『単一オブジェクトの上位に位置するものは、単一オブジェクトのみ』
  『じゃあコレクションは、いったいどこに位置するのか?』

  をどう考えたらいいかは、以下の図が入り口になると思います。
  

 【上位の単一のオブジェクト】

  下位の単一オブジェクトを
  取得するためのプロパティ。

  そのほとんど??が、
  その下位の単一オブジェクトを
  束ねているコレクションと同じ名前。
  (同名なので混乱しやすいので注意。)

   |
   |
   |__【下位のコレクション】_____【下位の単一オブジェクト01】
                    |     |
                    |     |__更に下位のコレクションや
       基本、          |         単一オブジェクト
       コレクションは、     |
       Itemプロパティか、    |
       Itemメソッドの      |_【下位の単一オブジェクト02】
       いずれかを持っていて、  |     |
       それが、そのヨコに居る、 |     |__更に下位のコレクションや
       単一のオブジェクトを   |         単一オブジェクト
       1個、ゲット=取得    |
       してくれます。      |
       『ユーザーが指定した   |_【下位の単一オブジェクト03】
       インデックス番号か    |     |
       名前』で。        |     |__更に下位のコレクションや
                    |         単一オブジェクト
                    |
  

※参考図
 https://euc-access-excel-db.com/00000WPPDF/object-model01.pdf
 https://euc-access-excel-db.com/00000WPPDF/get-object-basic01.pdf

※コレクションオブジェクトとの同居が無い、「単一オブジェクトのみ」の階層もあります。
 「Range」とか、「Font」とか、「Interior」とか。

  ※ただ、セルを表現している「Range」は、一応、「単一オブジェクト」なんですが
  「コレクションオブジェクトの性格も有している」、ちょっと特殊な、
  「単一オブジェクト」です。

※「(コレクションと同名の)上位のオブジェクトのプロパティ」は言わば、
 「オブジェクト取得のための」「入口」です。
 (例えばWorksheet単一オブジェクトを取得したい場合を考えたとき、
  その1つ上位のWorkbook単一が内包している「Worksheetsプロパティ」など。)

この場合、そのプロパティが直接、単一のオブジェクトを
 ユーザー側に投げ返してくれるわけではありません。
 (下位のコレクションを投げ返してくれるだけです。
  例えば「Workbook」単一オブジェクトが内包する「Worksheetsプロパティ」なら、
  下位の「Worksheetsコレクションオブジェクト」を投げ返すだけです。
  あとは何もしません。下位の単一のオブジェクトの取得はしないのです。)

 そのような段階で、
 実際・かつ・最終的に単一オブジェクトをゲット(取得)する動作をしてくれるのは、
 その「入口」から経由された、下位の「コレクション」の、
 「Item」という名前の「プロパティ・または・メソッド」、です。

  逆に言うと、ある単一オブジェクトを取得したかったら、
  上位の単一オブジェクトの中に、その複数形の名前のプロパティがあるはずなので、
 (=含まれているはずなので、
   =多くの場合、「s」が付いただけとか、「es」変形したものや、
   まんまで「collection」が付いただけのもの、などが含まれています。)
  そのプロパティを探し、そして 使えば、
「同名の・かつ・今いる階層の」コレクションオブジェクトにアクセスでき、
  最終的には、その中のItemメソッドかItemプロパティが、
  単一のオブジェクトを取得してくれる・・・ということになります。
  

  たとえば「WorkSheetオブジェクトってどうやって取得すんだっけ?」と思ったら・・・

  まずイミディエイトウィンドウにて、Parentプロパティ+TypeName関数で、
  その「1つ上位の単一オブジェクト」を調べます。
  「Workbook」という単一オブジェクトだと、判明するはずです。
   ↓
   ↓
  で、次に、オブジェクトブラウザにて、
  その「Workbook」単一オブジェクトのなかに、
  「WorkSheet」に「s」が付いたプロパティがあるはずなので・・・、
  つまり、
  「Workbook」単一オブジェクトの
      1段階下位に位置する
        「Worksheetsコレクショオブジェクト」
  と同じ名前のプロパティがあるはずなので、
  そのようなプロパティが無いかを探し、
   ↓
   ↓
  あれば、「それが目的のプロパティだ」、ということになるので、
  そのプロパティ(ここでは「Workbook.WorkSheets」プロパティ)や、それに関連する
  「WorkSheets」コレクションオブジェクトや
  「Sheets」コレクションオブジェクトのヘルプを読んでから、
   ↓
   ↓
  「Workbook.WorkSheets」プロパティを使って
  「Sheets」という名前のコレクションを取得し、
   ↓
   ↓
  その中の(「Sheets」の場合は)Itemプロパティで、
  「 WorkSheet 」という単一のオブジェクトが取得できます。

 (なぜWorkSheets」ではなくて「Sheets」を取得することになるのかは、
  そういう仕様になっている・・・という感じの 記述がヘルプになされています。
  コレクションは、必ずしも、1種類のみのオブジェクトを扱うわけではなく、
  同類の「似た」ものを集めるモノもあるようです。
  じゃあ、「Sheets」コレクションは階層構造の中のどこに居んの?と疑問になりますが
  まあ、そこまではわからなくても、かなり細かいシステム・機能を作るのでなければ、
  大きな問題にはならないと思います。多分。) 

  基本的に、Web検索しても出てこないオブジェクトを取得したいときは、
  基本的にはこのような調べ方をします。

  また、ヘルプを読めば、そんなことしなくてもすぐに取得の方法が見つかる、
  というか、書いてあることも多いです。

※繰り返しますが、ItemプロパティやItemメソッドはほとんどの市販書籍やWebサイトで
 「手抜き省略される」ため、
 その著者たちのせいで、「本来のオブジェクトモデル・階層構造その他」が
 「ある意味」「破壊されてしまい」、
 ヘルプの内容やオブジェクトブラウザとの整合性が、「非常に」とりにくくなります。
 (=ヘルプが何を言っているのかが、ワケわからなくなる)

 結果、「明確な説明も教えてもらえず」「そのうちわかるよ」とお茶を濁されて、
 みんな、挫折します。
 基本、「そのうちわかるよ」と言われたら、99.9%、「まず教えてもらえない」です。
 ひどいと「そのうちわかるよ」は、「自分、そんな細かいこと知らないし。」と
 同義だったりします。

 でも、上記のような図・構造で、
 「Itemを省略しないオブジェクト式の書き方」と、
 「長ったらしくなるからこそのオブジェクト変数の頻繁な利用」を
 マスターすれば、ヘルプやオブジェクトブラウザが扱えるようになりますから、
 ひいては、「自作関数化」「汎用化」もとてもやりやすくなりますので
 それで、上達が早まります。

 ヘルプやオブジェクトブラウザが扱えるようになることを「面倒」と
 お感じの方もいらっしゃるかと思いますが、
 それは誤解で、実際、Web情報ありき、よりも、ヘルプありきのWeb検索、
 のほうが圧倒的にミスやエラーが減ります。

 「短く書けるから優秀とか、スマート、とか、」、初心者の方々の学習にとっては、
 本当にばかばかしい、どーでもいいこと、ですよね。

「短く書くなんて言って、手抜きを教えないで!」
「初心者だと思って甘く見てウソを教えないで!」
「長くなってもいいから階層構造を一切省略しないで教えて!」
と言いたくなりますよね。

そんなことより、

 『 長かろうがスマートじゃなかろうが、
   できるだけ簡単に関数化できる書き方・関数に変形しやすい書き方・
   プログラムの若干システマティックなひな型 』

 を、教えてくれて、「最初は意味がわからなくてもいいから形から入る」、ほうが重要です。

 そういうことができる先生に習いたいですよね。

 学習を進める身としては・・・。習う側としては・・・。
  
  

「短く書ける人が関数化できないわけないじゃない」と言う人が居るかもしれませんが、
  でもそれは「詭弁」だと思います。

「短く書けること」と、「値やオブジェクトを返す自作関数」が思い通りに作れて
  「関数化・部品化」ができること、とは、

「特に初心者の場合」まったくと言っていいほど、関係がありません。
(※熟練者なら「短く書けるから関数化もできる」というケースもあるとは思いますが)
  
  

逆に、短く書こうと省略だらけになると、
 「関数化・汎用化」が「スッとできなくて」面倒くさくなってしまいます。

「関数化・汎用化」ができなければ、100%、初級の下のまま、上達できませんので、
短く書けても意味が無いです。

もちろん、腕があがってこれば短く書くことも必要になってくると思いますが、
初心者のうちは、短く書くことよりも、
「構造化」「部品化」する、
「エラーが発見しやすくなるように」書く
「場合によっては表レイアウトのように」書く
「のちのち関数化がしやすくなるように、あらかじめ、形だけでも整えて書いておく。
  最初は意味があまりわからなくても、
  そのひな型プログラムを作って守るだけでも上達が早まる」
ということのほうが重要です。
  
  
  

例:単一のWorksheetオブジェクトを取得したいとき=単一のWorksheetオブジェクトを取得するオブジェクト式を書きたいとき
にイメージする階層構造やコレクションの位置、プロパティの位置関係について
  
 
  Workbook単一オブジェクト(上位)の中に在る、
  「Worksheetsプロパティ」
   (下位のコレクション「だけ」をゲットする「だけ」の役目)
   (単一オブジェクトをゲットする機能は持っていません!)
     |
     |
     |
    Worksheetsコレクション(下位)の中に在る、
    「Itemプロパティ」→→→→→→→→→→→→→→【 単一のWorksheetオブジェクトたち】
                            (同じく下位)。
    (↑同じ階層に居る単一の            (Sheet1、Sheet2、Sheet3…など)
      オブジェクトを
      最終的に ゲットする役目)         
                          
  

※参考図
 https://euc-access-excel-db.com/00000WPPDF/object-model01.pdf
 https://euc-access-excel-db.com/00000WPPDF/get-object-basic02-disc-cut.pdf
  

上図のように考える理由は、TypeName関数とParentプロパティを使って、イミディエイトウィンドウにて、
『 ある単一オブジェクトの1つ上位のオブジェクト 』
を調べると、わかります。

まず
・コレクションオブジェクトの名前は「絶対に」出てきません。
・逆に、出てくるのは上位の「単一オブジェクトの名前」「だけ」、です。
・そして、
  コレクションの1つ上位(親)も、
  単一オブジェクトの1つ上位(親)も、
  同じ名前の「単一オブジェクト」の名前が出てきます。
  

だからです。
  

※「TypeName関数」は指定したモノのデータの「型」を教えてくれる(=返してくれる)命令です。
  
  

具体例で言うと、例えば、

? TypeName(ActiveSheet.Parent)

とやると「Workbook」が出てきます。
「Worksheets」や「Sheets」、とは出てきません。(いずれもコレクション名です。)
「s」が付いたり、「ies」が付いたり、といった名前は1つも出てこないのです。

ちなみに、「Sheets」コレクションは、ワークシート(Worksheet)もグラフシート(Chart)も
その他のシートも一括&個別管理するので、どちらの階層にも属していないイメージです。
(階層を超えたところ?3次元な階層?に居るイメージです。)

そして、

? TypeName(Sheets.Parent)

でEnterしても、

? TypeName(WorkSheets.Parent)

でEnterしても、

Workbook

と「同じ」「単一オブジェクト」の名前が返ってきます。
  
  

※ほんとうに、色々と、エラそうなことを言ってしまってすみません。

ただ、私はVBAはExcelではなく、Accessから入ったのですが、ExcelVBAが最初のうちは難解でしたが、
よくよくExcelの本やレジェンドさんたちのホームページを見て観察してみると、

「オブジェクトモデルの一覧図があれば一目瞭然なのにそれを使わない愚行。」
「できるだけ簡単に説明しようとする意図とは裏腹に、オブジェクト式の階層やオブジェクト変数の ” 省略のし過ぎ ” でかえって非効率と生徒の挫折を生んでいるという愚かさ。」
「特に省略されるのは、上位の階層構造と「Item」という名前のプロパティやメソッド」
「そういう手抜きレッスン・手抜き教習が 異常に多すぎる」
「特に初心者本に」
ということに気が付いてしまいました。

「結果、難解だったのは ”この省略と手抜き教習のせい ”」だったのです。

皆さまには、そういう回り道をしてほしくないと思い、エラそうなことを書いてしまいました。

ほんとうに、すみません・・・・。
  
  
  

==============================
  

今回は以上です。

==========================================================================

バックナンバー目次とサンプル号
  
https://euc-access-excel-db.com/tips/ct07_se/ct075012_xls2k_vba_tips/mag2-01
  
  

----------------------------------------------------------------------
■独学者が1年後にExcelVBAを爆発的に上達させるための最低限の基礎知識メモ(ダイジェスト)
発行システム:『まぐまぐ!』 http://www.mag2.com/
配信中止はこちら https://www.mag2.com/m/0001691660.html
----------------------------------------------------------------------