● 用語:「オブジェクト変数」とは?(ついでに「コレクション」についても少し・・・)
※まだ書きかけです。すみません。
※間違ってたらすみません。
※メモ書きなので、自分でも意味不明な箇所も多いです。ごめんなさい。
※★ 自分で言ってりゃ世話無いですが・・・本当にすみませんが、本記事は(一応参考程度にはなると思いますが、でも)、「古くてちょっといいかげん」ですので、先に必ず以下のページをお読み下さい。
『 ★独学者が1年後にExcelVBAを爆発的に伸ばすための最低限の基礎知識メモ(ダイジェスト):★ (09)挫折しないための「コレクション」とは? 』
「オブジェクト変数」とは、文字列や数値ではなく、「オブジェクト」という
「ユニット丸ごと・その機能丸ごと・入力できるモノならその入力値丸ごと」を「代入」できてしまう変数のことです。
普通の変数とは違う、ちょっと「特殊といえば特殊」な変数です。
プログラムにて、
「Dim ×× As オブジェクト名」
という形で変数を宣言すると、「××」が「オブジェクト変数」となります。
明確なオブジェクトの種類が分からない場合は、
「Dim ×× As Object」
とか、
「Dim ×× As Variant」
などと宣言しても良いです。
「Object」や「Variant」は「どんな種類のオブジェクトにも対応できるオールマイティな型ですよ~!」という意味になります。
(※★重要注意!!:Variant型の変数には、数値や文字列などの文字ベースの一般データも代入できます。ただ、生データやオブジェクト式が代入された瞬間に内部的に、そのデータにもっともふさわしい型に自動変換されます。ただし、「もっともふさわしい=目的に完全に合致する」という意味ではありません。残念ながら、「変えられたくない型に勝手に変えられてしまう」ということもちょいちょいあるので注意が必要です。必ず、ローカルウィンドウ、イミディエイトウィンドウ、ウォッチ式ウィンドウなどでの「現時点の変数の型と実際の内容」のチェックの方法を絶対に学んでおいてください。)
なお、「変数なんか全部VariantでOK!型指定なんて必要なし!」という説明をされることがありますが、それは絶対に無視して聞かないでください。
なぜなら、そんなことをすると、「初心者本をある程度終えた後の」「VBAの真のスタートライン」である、「値やオブジェクトを返す自作関数の自由な作成」ができなくなってしまうからです。
そうなってしまうと、「初級の下か初級の中」の腕前にとどまってしまい、つまり、マクロの記録とさほど変わらないコードしか書けません。
中級になんて、「死んでもなれません。」
当然、「挫折」も待っています。
断言します。
なので、私たちド素人は、変数についての細かい理解は必須なのです。
といいますか、そんな程度のことすらしたくない・あるいは時間が無くてできない場合は、マジで、最初からVBAなんて勉強しない方がいいです。
これは「嫌味で言っているのではなくて」、マジで、最初からVBAなんて勉強しない方がいいです。
なぜなら、お金・または・時間をドブに捨てるだけだからです。それが火を見るよりもあきらかだからです。
もしそうなりそうな感じでしたら、VBAに触れないことはまったく恥ずかしいことではないので、安い外注さんか学生さんバイトなどをうまく使って処理してください。
むしろ、無理してVBAに触れるほうが恥ずかしくて愚か、です。
「変数なんか全部VariantでOK!型指定なんて必要なし!」だなんて、どんだけ甘やかすつもりなんだ?そんなことで、成長できるわけがないじゃないか、真剣じゃないだろ!もともと教える気が無いんだろ!あなたがたは!ということに、いいかげん、ExcelVBAの教育業界は目覚めてほしいと思います。
ビジネスパーソンだって、それくらい理解できる。なぜ、皆さんの能力を信じない?と言いたいです。
(※参考01:「Dim ×× As オブジェクト名」という形で、明示的にオブジェクトの種類の名前で変数宣言することを「事前バインディング」、それに対して、:「Dim ×× As Object」という感じでObjectやVariantで変数宣言することを「実行時バインディング」と呼びます。※参考:『 事前バインディング・実行時バインディング」について(自信まるでなし)』)
なお、ちょっと横道にそれて、&、説明が難しくなってしまってすみませんが、
このときオブジェクト変数に代入されるのは、
「オブジェクト丸ごとのコピー」、ではなく、
「代入したオブジェクト丸ごとへの参照」だそうです。
で、いきなりですみませんが、その「オブジェクトへの参照」・・・のイメージ・・・ですが・・・、それは次のような感じです。
@「オブジェクトへの参照」とは、
オブジェクトを「リモコン操作」できるようにするための・・・、
・オブジェクトに対しての住所情報
・オブジェクトへの位置情報
・オブジェクトへのトンネル情報
・オブジェクトへのリンク情報
・オブジェクトへのショートカットアイコン
・今この場所と、ある1つのオブジェクトを電波でつなぐ・・・
そのための情報
これらはすべて、あくまでも「イメージ」ですが、でもあたらずとも遠からず、だと思います。(実際には、オブジェクトにアクセスするためのメモリアドレス?、ということなのかもしれません。ちゃんとわかっていなくてすみません。)
「なんで、オブジェクトの丸ごとコピーじゃ無くて参照なの?」ということについては・・・・
推測でしかありませんが、
オブジェクトの丸ごとコピーを変数に代入してしまうと・・・
動かしたいのはオブジェクトの「大元(おおもと)」のほうなので、
コピーを動かしたところで連動してないので、ダメ・・・
・・・という感じなのかもしれません。(よくわかりません!すみません!)
ここで注意というか、意識したいのは、
オブジェクト変数に代入されるのは、
厳密には「目的のオブジェクト丸ごとへの参照」だけれども、
でも、操作自体は、現実には、
目的のオブジェクトの持つすべての機能や入力値・設定値を操れる(動かせる)ため、
見かけ上は、
「目的のオブジェクトのすべてが丸っとオブジェクト変数に代入された」
という感じに見えるから、そうとらえていい。
・・・・ということです。
特に私らど素人やVBA初心者の方々にはそのほうがわかりやすいです。
短く言うと・・・、
オブジェクト変数に代入されるのは、
厳密には「目的のオブジェクト丸ごとへの参照」だけれども、
でも「目的のオブジェクトの全てが丸っとオブジェクト変数に代入された」
ととらえていい。
・・・ということです。
厳密なプログラミングをしない場合やVBAの覚え始めはそれで問題ないのでそう捉えちゃっていい・・・、ということです。
※参考記事
『Access2000VBA・Excel2000VBA独学~★★★超重要!!!「実際の機能や画面等々」と「VBAオブジェクト」との対応。例えば「Application」って何?Workbookとの関係は?』
『Access2000VBA・Excel2000VBA独学~用語:”目に見える”「メソッド・プロパティ・列挙(=Enum)・定数(=Const)」と右クリックメニューの画面の関係について~』
※絶対にこちらも読んでおいてください!! ↓↓↓
★★★★★★★★★★★★★★★★ 超重要!!必読!!ExcelVBAが上達するかどうかの最初の分かれ道!オブジェクトとオブジェクト式について~★★★★★★★★★★★★★★★★
少し詳しく、でもそこそこまとめた記事です。
ちなみにですが、「オブジェクトの取得とは?」ということになってくると、次のようになると思います。
@オブジェクトを「リモコン操作」できるようにするために・・・、
・オブジェクトに対しての住所情報を取得する
・オブジェクトへの位置情報を取得する
・オブジェクトへのトンネル情報を取得する
・オブジェクトへのリンク情報を取得する
・オブジェクトへのショートカットアイコンを取得する・・・
・今この場所と、ある1つのオブジェクトを電波でつなぐ・・・
そのための情報を取得する・・・
また、「オブジェクトを取得する」とは、
・「操作対象のオブジェクトを1つに特定する。」とか、
・「操作対象としたい、何らかの1つのオブジェクトを、選択する。」
・「操作対象としたい、何らかの1つのオブジェクトが、”選択された”、という状態にする。」
という意味の作業でもあります。
例えばヘルプを読んでいるときは、その文脈等を考えて、一番しっくりくる訳をあてはめればいいと思います。
※こちらも必読です→『「オブジェクトを取得する」とは?01 』
で?、「オブジェクト」とは?、「オブジェクト」って何?ということになるんですが、「オブジェクト」とは、端的に言うと、例えばExcelの場合であれば、「セル、シート、ブック、ピボットテーブル、各種グラフ、オートシェイプ、テキストボックス、コマンドボタン、リストボックス、ダイアログ画面の機能、VBE管理機能(VBEオブジェクト:アクセスするにはこちら、MicrosoftQuery機能(QueryTableオブジェクト)、エラー管理機能(Errオブジェクト)、複数シート管理機能(Worksheetsコレクション)、ODBC接続機能(ODBCConnectionオブジェクト)、ワークシートのアウトライン機能(Wordのスタイルのアウトラインと似た感じの機能:Outlineオブジェクト)、ADOやDAO機能(外部データベース操作関連の各種オブジェクト)」等々をさします。(ADOやDAO機能、MicrosoftQuery機能はWordやAccessからも利用できる、Excelからは独立した別個の機能・ユニットですが・・・)
Excel、Word、Access、Outlook、PowerPoint、すべてひっくるめてで言うと、「何らかの機能をもったユニット・機能の集合体・道具・ツール」のことをさします。
これは、目に見える・見えない・大きい・小さいに関係なく、「”ユニットと化した”各種の機能・機能の集合体・メニューコマンド・ツールたち」のことをさします。
「”ユニットと化した”」とは、「単一の機能だけではなく、複数の機能をもったユニット・複数の色んな機能が集まったユニット」という意味で捉えてもらってよいと思います。まさに「機能の集合体」です。
「部品、パーツ、ミニミニロボット」という感じで考えてもいいと思います。
画面上に目に見える・見えない・大きい・小さい、にかかわらず、とにかく「ユニット、部品、パーツ、ミニミニロボット、という感じの 複合機能体 が " オブジェクト " 。」です。
「単なる文字列データ・文字系の一般データ(文字列・数値・日付データ・論理値(True/Falseなどの2値)」とは対照的な、それとの「対義語」としての、「(実際には微妙ですが)かたちあるもの・イメージ的には立体的なもの・3D的なもの」です。
そして、それらの「実際の画面上に見えるもの」も「見えないもの」も、大きいものも小さいものも、「3D的なもの・かたちあるもの」の、すべてを、「プログラムコード上で」表現しているのが、「オブジェクト式」です。
つまり、オブジェクトとは、プログラミング上では「オブジェクト式」のことをさします。
そしてそれが「オブジェクト変数」に代入されます。
「実際の画面上に目に見えるオブジェクト」=「オブジェクト式」
「実際の画面上に目には見えないオブジェクト」=「オブジェクト式」
「大きめなオブジェクト(でもちゃんと機能の集合体」=「オブジェクト式」
「小さめなオブジェクト(同上)」=「オブジェクト式」
・・・ということなのです。
逆も言えます。
「オブジェクト式」=「実際の画面上に目に見えるオブジェクト(パーツ・ユニット)」
「オブジェクト式」=「実際の画面上に目には見えないオブジェクト」
「オブジェクト式」=「大きめなオブジェクト」
「オブジェクト式」=「小さめなオブジェクト」
オブジェクトたちを「オブジェクト式」という文字ベースの形に書き表すことができれば、「オブジェクト変数」にも代入できます。
※「オブジェクト式」は、目に見える・見えないなどには関係なく、「3D的なもの・かたちあるもの・複数の機能を持ったユニット・パーツ・部品」を、文字列の形に書き表したものです。(階層構造・親子関係を表現しつつ)
なので、「オブジェクトを取得する」とは、「オブジェクトをGETする」、「=パーツ、部品、ミニミニロボットをGETする」「1つ選択する」という感じでもあります。
(あるいは、オブジェクトに「接続する」というイメージでもいいかもしれません。)
イコール、「オブジェクト式を書く」ということでもあります。
そしてその「オブジェクト(=オブジェクト式)=パーツ、部品、ミニミニロボットをGETする」には(=各オブジェクトに接続するには)、以下のような方法があります。
(a)1階層「上位」の「単一オブジェクト」のプロパティが取ってきてくれて、ユーザー側に投げ返して(渡して)くれるものをGETする
(例えば、Application.Workbooksプロパティや、Workbook.Worksheetsプロパティ、Worksheet.Rangeプロパティ、などを使い、それらが投げ返してくれるものをGETする。)
(b)1階層「上位」の「単一オブジェクト」のメソッドが取ってきてくれてユーザー側に投げ返して(渡して)くれるものをGETする
(例えば、Range.FindNextメソッド、Worksheet.PivotTablesメソッド、Workbook.NewWindowメソッド、Application.Unionメソッドなどを使い、それらが投げ返してくれるものをGETする。)
(c)(直接の)「上位」「ではない」、その他のオブジェクト(例えばコレクションなど)のプロパティやメソッドが取ってきてくれて、ユーザー側に投げ返して(渡して)くれるものをGETする
(例えば、Workbooks.Itemプロパティ、Workbooks.Addメソッド、Worksheets.Itemプロパティ、Worksheets.Addメソッドなどを使い、それらが投げ返してくれるものをGETする。※AddメソッドやOpenメソッドなどは、「新規作成」や「開く」などをしながら、同時に、それらのモノをオブジェクトとしても投げ返してくれます。)
(d)VBA(VBE6.DLL、あるいはVBA7.DLLなど)に属する関数が取ってきてくれて、ユーザー側に投げ返して(渡して)くれるものをGETする
(例えば、CreateObject関数やGetObject関数などを使い、それらが投げ返してくれるものをGETする。)
※CreateObject関数やGetObject関数なども、メソッドと似てて、何らかの動作をしながら、同時に、それらのモノをオブジェクトとしても投げ返してくれます。例えばCreateObject関数は何かを「新規作成」をしながら、同時にそれをオブジェクトとしてエンドユーザー側に投げ返してくれます。
※「(VBE6.DLL、あるいはVBA7.DLLなど)に属する・属さない」はオブジェクトブラウザを見るとわかります。
(e)Office全体(MSO××.DLL)のオブジェクトに属するプロパティやメソッドが取ってきてくれて、ユーザー側に投げ返して(渡して)くれるものをGETする
(例えば、CommandBars.Itemプロパティ、CommandBars.Add メソッド、などを使い、それらが投げ返してくれるものをGETする。)
(f)イベントの引数からオブジェクトをGETする
(例えば、Worksheet.SelectionChangeイベントなどの引数の「Target」、などを使い、それらが投げ返してくれるものをGETする。)
※1階層「上位」=親、1階層「上位」の「単一の」オブジェクト=親オブジェクト
※例えば、Rangeプロパティには、『 同名・かつ・「単一のセル・あるいは・セルの集まり」を取得してくれるプロパティ 』だけども、「でも少し性格の異なる」Rangeプロパティが存在します。
例えば「Worksheet.Rangeプロパティ」、「Range.Rangeプロパティ」、「AutoFilter.Rangeプロパティ」はすべて、「単一のセル・または・セルの集まり」を取得できるプロパティ(=「単一のセル・または・セルの集まり」に接続できるプロパティ)ですが、少しずつ性格が異なります。
親オブジェクトが異なるからです。
通常、親オブジェクトが変わると、性格も少しだけ異なってきます。なので、RangeはRangeでも「ワークシートのセルの集まり」の場合なら、「Worksheet.Range プロパティ」と表現して「ワークシートのRange(セルの集まり)ですよ」と明示的に表現しなければ「誤解を招いてしまいます」し、そもそも意図したプログラム動作になりません。
また、プロパティによっては、親オブジェクトの、さらに「親オブジェクト」もちゃんと書かないとエラーになる場合もあります。
このような親オブジェクトとセットでのプロパティの階層構造については、2010のヘルプには「Worksheet.Rangeプロパティ」、「Range.Rangeプロパティ」、「AutoFilter.Rangeプロパティ」といった形でしっかりと書いてあります。(2013のヘルプは一応出てくる場合の方が多いですが、2010のヘルプと比べると全然ちゃんとしてないし、誤作動みたいなものをよく起こします。2016のヘルプはわかりませんが2013と似ているかもしれません。)
では以下、若干の詳細説明です。
(a)1階層「上位」の「単一オブジェクト」のプロパティが取ってきてくれて、ユーザー側に投げ返して(渡して)くれるものをGETする
(Excel、Word、Access、ユーザーフォーム、多くがこのパターンです。ExcelならWorksheet.Rangeプロパティ、Worksheet.QueryTablesプロパティ、Workbook.Worksheetsプロパティ、Application.Workbooksプロパティ、など。
Accessなら、Application.Formsプロパティなど。ユーザーフォームならUserForm.Controlsプロパティ、など。Accessやユーザーフォームのヘルプは、Excelのヘルプのように「 ×××オブジェクトを取得するには、×××プロパティを使用します」などと明確に書かれていないので間違えてしまいそうですが、例えばAccessならFormsプロパティというものが存在して、そこから単一フォームを取得しているようです。僕自身、今までコレクションで直接、フォームを取得していると誤解していました。)
※1階層「上位」=親、1階層「上位」の「単一の」オブジェクト=親オブジェクト
(b)1階層「上位」の「単一オブジェクト」のメソッドが取ってきてくれてユーザー側に投げ返して(渡して)くれるものをGETする
(Excelの場合、Application.Unionメソッド、Worksheet.PivotTablesメソッド、など。)
※1階層「上位」=親、1階層「上位」の「単一の」オブジェクト=親オブジェクト
(c)(直接の)「上位」「ではない」、その他のオブジェクト(例えばコレクションなど)のプロパh値やメソッドが取ってきてくれて、ユーザー側に投げ返して(渡して)くれるものをGETする
(Excelの場合、Workbooks.Openメソッド、Workbooks.Addメソッド、QueryTables.Addメソッド、PivotTables.Addメソッド、など。OpenやAddは、ExcelのみならずOffice全体でも多くのコレクションオブジェクトが保持・保有・内包しているメソッドです。Openはどんなオブジェクトでもたいていは既存のものを開きながら、Addの場合は新規作成追加をしながら、それをオブジェクトとしてユーザー側に投げ返してくれます。プロパティも同様に存在します。)
※「コレクション=コレクションオブジェクト」です。
コレクションについて→→『~用語:ExcelVBA~「コレクション(=コレクションオブジェクト)」とは?~』
※★★★ 超超超・重要事項!!!★★★ →→→ 1階層「上位」=親、1階層「上位」のオブジェクト=親オブジェクト、なんですが、コレクションオブジェクトは単一オブジェクトの「親」=「上位」という位置関係にはありません。
そして、階層が「親であること=1階層分、上であること」と、「複数の単一オブジェクトたちを束ねる・含む(束ねて管理しているだけ)」ということ、実は「まったくの別の事柄・べつもの」であり、もっと言うとまったくの「無関係」です。
このことは、VBAの学習(特に独学)にとって、「超重要事項」ですので、必ず意識しておきます。
でないと、ヘルプとオブジェクトブラウザの意味が通じなくなってしまう(=読めなくなってしまう)からです。
コレクションオブジェクトは、「複数の単一のオブジェクトを束ねる機能・単一オブジェクトたちをゴソッと一括処理する機能」を有してはいますが、束ねてはいますが・でも・「親」の位置には「居ない」のです。「兄弟」的な位置に居るイメージです。
「兄弟」的な位置、「同じ階層」に居つつ・・・、でも、複数の単一オブジェクトたちを束ね・含み・管理している・・・というイメージです。
それは「オブジェクト式」の「ドット」の位置・・・、といいますか、「ドットからドットまでの間に記述されているもの」、を「よく観察」すれば、おそらく多くの方が「言われてみると確かにそうなっている・・・」とイメージ・実感できるのではないかと思います。
※2020/02/18追記:以下、間違っていました。すみません。
もともと、VBAにおける、オブジェクト式における、「1階層分」とは、「ドットからドットまで!」を指します。
もしコレクションオブジェクトが、単一オブジェクトの「1つ上の階層」に位置することになっているのであれば、コレクションだけででもドットからドットまでが占有されていないといけません。つまり、コレクションと単一オブジェクトの間にドットが無いといけない、ということになります。逆に、もしそうなっていれば『 コレクションは単一オブジェクトの「親」だ 』と言えます。
でも現実にはそんな風になってはいません。
例えばコレクションを指定したいときはカッコや引数を書かず、一方、単一オブジェクトを指定したいときはカッコや引数(名前やインデックス番号)を書く、という風に、「書き分けの違いがあるだけ」で、ドットからドットまでにもうひとつ、「コレクションの階層専用のドット」が入る・増えるわけではありません。
繰り返しになりますが、VBAにおける、オブジェクト式における、「1階層分」とは、「ドットからドットまで!」を指します。
上記の記述は間違いでした。すみません。
ドットは、「階層の切れ目」を表現しているのではなく、「オブジェクトの切れ目」、を表現しているのでした。
各コレクションにおける、「Item」という名前のプロパティやメソッドのことを学習していなかったために、上記のような理解のし間違いをしてしまっていました。
ごめんなさい。お詫びします。
「ドットは基本、オブジェクトの切れ目」です。
「階層の切れ目」は、「 ”下位のコレクションオブジェクト” を取得するプロパティ+ドット+ItemプロパティorItemメソッド」がひとつの階層の区切りです。
ただ、コレクションを持たない単一オブジェクトもあるので、例外もあります。
が、多くは、
「Workbooks.Item("ブック名")」とか、
「Worksheets.Item("シート名")」とか、
「Charts.Item("グラフシート名")」とか、
「Pivottables.Item("ピボットテーブル名")」
といった感じで、
「Item」とセットになったところまでが含まれて、Item(××)の次のドットが、「階層の区切り」です。
ただ、「Item」は多くのサンプルで(ヘルプのサンプルでさえ)省略されるので、このことがとても発見しにくいです。気づきにくいです。
「コレクションは複数の単一オブジェクトを含んでいる」「単一オブジェクトたちはコレクションに含まれている」という表現がよくなされます。当サイトでもそういう言い方をよくしますが、でも、だからといって、コレクションが単一オブジェクトの「親=1階層分、上」に位置しているわけではないのです。同じ階層(あるいは別の空間)に居る感じです。同じ階層(あるいは別の空間)に居つつ、単一オブジェクトたちを含み、管理しているイメージです。
そう、「含む」というより、「束ねて管理しているだけ」というイメージのほうが強いと思います。
(その証拠と言っては何ですが、たとえば「Sheetsコレクションオブジェクト」なんて、階層構造を全く無視して、ワークシートもグラフシートも含んで束ねて管理してしまっています。WorksheetオブジェクトやChartオブジェクトは同じ階層に居てお互いに上下関係は無いのに、両方をいっしょくたに管理しています。)
コレクションが単一オブジェクトの「1階層上」のオブジェクトだと誤解すると、VBAのオブジェクト構造の全体像がわからなくなり、オブジェクトブラウザやヘルプも読めなくなります(=意味が通じなくなります。)
結果(またまた繰り返しになりますが)、階層が「親であること=1階層分、上であること」と、「複数の単一オブジェクトたちを束ねる・含む(束ねて管理しているだけ)」ということ、実は「まったくの別の事柄・べつもの」「無関係」と考えるほうがいいと思います。そうすれば、オブジェクトブラウザやヘルプが読めるようになります(=意味が通じてきます。)
(d)VBA(VBE6.DLL、あるいはVBA7.DLLなど)に属する関数が取ってきてくれて、ユーザー側に投げ返して(渡して)くれるものをGETする
(Excel、Word、Access、PowerPoint等共通で、GetObject関数や、CreateObject関数、など。GetObject関数は既存のファイルを開きつつ、それをオブジェクトとして投げ返してくれます。CreateObject関数は、新規のファイルを作りつつ、それをオブジェクトとして投げ返してくれます。なお、GetObject関数は、すでに開いている既存ファイルをパスがわからなくてもApplicationオブジェクトを取得できます。なので、それ経由で既に開いているファイルもオブジェクトとして取得できます。)
(e)Office全体(MSO××.DLL)のオブジェクトに属するプロパティやメソッドが取ってきてくれて、ユーザー側に投げ返して(渡して)くれるものをGETする
(Excel、Word、Access、PowerPoint等共通で、古いオブジェクトとメソッドですが例えば CommandBars.Addメソッド、など。プロパティも同じように存在します。)
(f)イベントの引数からオブジェクトをGETする
イベントの引数にオブジェクトが含まれる場合、そこからもオブジェクトをGETできることがあるそうです。
例えば、ワークシートをBeforeDoubleClickイベントには「Target」というRangeオブジェクトを表す引数があります。
なので、ダブルクリックしたセルのアドレスなどを、イベントプロシージャの実行中に調べることができます。
ThisWorkbookのSheetBeforeDoubleClickイベントでも同じことができます。すべてのシート共通にやれます。
例
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 |
' ' 'シートのBeforeDoubleClickイベントの場合 Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) Dim sht As Worksheet Set sht = Target.Worksheet Stop Debug.Print Target.Address Debug.Print Target.Worksheet.Name 'エラー回避用コード If Target.CountLarge <> 1 Then Exit Sub End Sub ' ' 'ThisWorkbookのSheetBeforeDoubleClickイベントの場合 Private Sub Workbook_SheetBeforeDoubleClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean) Dim sht As Worksheet Set sht = Target.Worksheet Stop Debug.Print Target.Address Debug.Print Target.Worksheet.Name 'エラー回避用コード If Target.CountLarge <> 1 Then Exit Sub End Sub ' ' |
※ちなみにですが、「一般変数」にとっての「生データ」は、「文字列や数値、日付データやTrue・False」といった文字ベースの値ですが、「オブジェクト変数」にとっての(言わば)「生データ」に相当するものは「オブジェクト式」・・・という感じになります。
「文字ベースの一般データ」は変数に代入しないと生のままでは扱いにくいのに、オブジェクトは変数に代入しなくても扱えてしまうので、それがVBA初心者にとっての混乱を招くもと・・・、かもしれません。
逆に言うと、『 常に、オブジェクトもできるだけオブジェクト変数に代入する 』というクセにしておく・それをちゃんと先生に習う、と、疑問点も的をついたものが増えはじめ、コピペばかりしている人と比べると十数倍か人によっては数十倍のスピードで上達すると思います。特に階層構造に疑問をもち、それが頭の中で省略せずにきちんとイメージでき、かつ、本記事でも言っていますように、「5つの機能」は「全部オブジェクトの中に内包されているんだ!それを命令や機能として内側から引き出して使うんだ!」ということが明確になると、さらに上達が早まると思います。それくらい、オブジェクト変数に代入することと、階層構造を省略しないことは、VBA初心者の学習にとって、死ぬほど重要です。ExcelVBAが上達しない人は、100%、オブジェクト変数が扱えず・”階層構造”や”内包”の「意味」が理解できていません。(教える側がしっかり教えないのである意味「犠牲者」、なんだと思いますけど・・・。)そのため、他の重要なほとどんどのことが理解できません。上達するわけがないのです。VBA(DAO、ADOも)のオブジェクトはどこもかしこも「階層構造」が「ベース」になっているのですから。「ベース」が理解できない人が上達するわけないのです。そしてそれが理解できないために設計に対しても無頓着になり、無駄な「絆創膏プログラム」を量産することになります。設計ができないために無駄なプログラムを書きすぎる羽目に陥るため、かえってメンテやらなんやらのコスト・その他のコストを上げてしまうという・・・。外注さんに任せることになったときもデータの持ち方からしてムダだらけで、払う必要のない・例えば「数十万以上の無駄料金」を払わされる羽目になってしまいます。
話が逸れてすみません!(でもとても重要なことではありました。)
「オブジェクトとは?」の話に戻ります。
前述の「セル、シート、ブック、ピボットテーブル、各種グラフ、オートシェイプ、テキストボックス、コマンドボタン、リストボックス、ダイアログ画面の機能、」等々、目に見えるものだけでも見てみてください。
どれも複数の機能を持っていますよね。
そして、それぞれ大なり小なり「ユニット」という感じで捉えることができるものばかりだと思います。
また、メニューコマンドにしても複数の機能を持っているものもあります。
(なお、ExcelにはExcel独自の、AccessにはAccess独自の、WordにはWord独自の、PowerPointにはPowerPoint独自の、それぞれ、「オブジェクト」があります。)
目に見えない・見えにくいオブジェクトですと、「エラー管理機能(Errオブジェクト)」、「複数シート管理機能(Worksheetsコレクション)」、「ODBC接続機能(ODBCConnectionオブジェクト)」、「ワークシートのアウトライン機能(Wordのスタイルのアウトラインと似た感じの機能:Outlineオブジェクト)」、などがあります。ADOやDAO(外部データベース操作機能)なども、ExcelやWordからは独立していますが、一応(目には見えない)オブジェクトがいっぱいあります。
そしてこれらのすべてが、「複数の機能の集合体」です。
例えば
「エラー管理機能(Errオブジェクト)」では、
「エラー内容やエラー番号の表示機能」
「エラー発生時のプログラム実行継続機能」
「エラー生成機能」
「エラーの発生元を探る機能」
などを保持しています。
「DAO(Data Access Objectsオブジェクト)」では、
「外部データベースへの接続機能」
「SQL実行機能」
「列の管理機能」
「行の移動機能」
「列の移動機能」
「データの書き換え、削除、追加の機能」
「テーブル定義機能(例えば閉じたExcelファイルの中に・閉じたまま表を作れます)」
「クエリ定義機能」
など、複数のたくたんの機能を保持しています。
その他の「目に見えないオブジェクト」もすべて、そのように複数の機能を持っています。
※参考記事→『用語:VBAプログラミングでの「オブジェクト」 について』
ちなみにですが、「オブジェクトが持つ機能」にはどんなものがあるでしょうか?
ここではあまり詳しくはお話しできませんが、オブジェクトは大きくわけて、主に「5つの機能」を持っています。前述のような複数の機能を含めたうえで、大分類として、「5つの機能」を持っています。
(「持つ=保持・保有・内包している・・・」という意味です。「5つ」とは、僕が勝手に言っていることです。)
※注:これより前では、その「機能」については、「メニュー単位のかなり細かい機能」のことをさしていましたが、これ以降ではそれらも含めて大きくグルーピングしてとらえます。
ではその「5つの機能」とは何か?ということなんですが、それは、
・「階層構造(≒階層構造上下自由往来機能)」
・「プロパティ」
・「メソッド」
・「イベント」
・「ユーザー入力値」
の5つです。
(繰り返しますが、僕が勝手に言っていることです)
※「5つの機能」に関する補足
一般的には「5つの機能」なんていう話をする人(例えば講師さんとか先輩さんとか)はいません(僕が勝手に言ってるだけなので)。
オブジェクトが内包するものに関しては、「プロパティ」「メソッド」の2つの機能の話が多く、「イベント」「階層構造(≒階層構造上下自由往来機能)」や「ユーザー入力値」についてはあまり多くは解説されません。
といいますか、「プロパティ」「メソッド」の話すら、「それらはオブジェクトが内包するものである」という話すら、されていないのではないでしょうか?「内包される」「機能だ」という話すらされていないのではないでしょうか?
しかし、VBAが短期間に習得できない人・中級に上がったとたん挫折する人、初心者本を読んだだけでスグに挫折してしまった人、「自力でエラーが解決できない人」は、まず間違いないなくこの3つの機能のことを理解していません。(特に、階層構造。”単一オブジェクト” と ”コレクションオブジェクト” の違いや位置関係とかも。)
もっと言うと、この5つの機能が(VBA関数やステートメントのように)、「オブジェクトの外側にある(位置している)」「変数(オブジェクト変数)の外側にある(位置している)」と勘違いすらしています。
「5つの機能」が、「全部 オブジェクトの内側に含まれる」「内包される」ということがまったく理解できていません。
そのため、「オブジェクトのオブジェクト変数への代入」のことが全然理解できません。
(もしかしたら「オブジェクト式」の意味すら理解していないかも・・・。)
「5つの機能は、全部、オブジェクトの中に、内包される」。
「一般変数(=文字ベースの値:文字列・数値・日付・2値など)はVBA関数や演算子などを使って、ある意味外部・外側から動かす」けれど、
「オブジェクト変数(=オブジェクト式)は内包される5つの機能を、ある意味内側から引き出す形で動かす」という違いがある・・・、
(ステートメントを使うのは両方とも同じ)
・・・ということが頭の中で明確に「図として」「映像として」イメージできていないため、「オブジェクトのオブジェクト変数への代入」のことが全然理解できません。
ひいてはヘルプも理解できないし、オブジェクトブラウザの意味も理解できません。
(プログラムコードとしての「オブジェクト」とは?・・・ → → → 「オブジェクト式」、あるいは「CreateObject関数やGetObject関数などのVBA関数」、あるいは「オブジェクトを返す能力を持ったプロパティやメソッドなど」を使うことで、「オブジェクト」として返されてくる「モノ・ユニット」のこと。)
VBAのオブジェクト操作で、もっとも重要なことの一つは、「オブジェクトは階層構造になっていてその全体図が存在する」ということと、「その図を使って全体を把握しながら学ぶほうが短期間に腕が上がる」+「その階層構造を省略しないオブジェクト式の書き方を学ぶ方が上達が早い」ということを理解することだと思います。そのようにお考えください。
逆に言うと、「階層構造」や「階層構造を省略しないオブジェクト式の書き方」「5つの機能はオブジェクトに内包される」ということなどが分からない人が、VBAプログラミングが理解できることは、「永遠にない」、ということになります。
実際僕も、階層構造について理解できて、ようやくヘルプやオブジェクトブラウザが使えるようになってきたんですが、その後の僕と前の僕では、(もちろんまだ全部は理解できないまでも)でも、VBAの理解や作成のスピードが10~20倍くらいアップしたと自分自身で実感できています。
今までよくわからなかったExcelVBAの市販本が、突然、おおむね全部がスラスラわかるようになり、だから逆に「なんで20年経っても未だにこんな教え方してるんだろう?絆創膏貼るだけみたいな・・・」と、感じるようになってしまいました。
僕がそのようになれた、とっても重要なヒントをくれたものすごい書籍があるので、ご紹介しておきます。
『いちばんやさしいExcelVBAの教本 人気講師が教える実務に役立つマクロの始め方』
まったくの初心者の方にはもしかしたら少し難しいかもしれませんが(特に8章以降)、真面目に中級への上達を考えているかたは必読です。自分のレベルが上がるにしたがって、「その章にその項目をその順番で書いた意味・重要性」がわかるようになると思います。
他の本とは「次元」がまったく違ってました。
他の本にはない、Variant型を多用した時のローカルウィンドウでの変数の中身の確認の重要性、などについても、さりげなく導いています。
最初に読んだ時はわからなかったけど、「オブジェクトを取得できるプロパティと2種類ある」の話を読んだら、そこからヘルプを読み直したら、今までの十数倍か20倍以上のスピードで他の応用のことが理解できるようになりました。なんだ、ヘルプに全部書いてあるじゃん、という感じです。オブジェクトブラウザの意味・価値もわかるようになってきました。残念ながら この本の「本当の意味・すごみ」がわからない人は、何の本質も学ばずに素通りしてしまうかもしれませんが、でももしそうなったとしてもいつか「読み直した」ときに、そのすごさが分かると思いますので、買って絶対に損はない価値の高い本です。
Excelの本で「買って損はない」と思った本は4、5冊くらいありますが、そのうちの1冊で、ナンバーワンの本でした。初心者本の中では、いままでのExcelVBAのどのレジェンドさんが出版した本よりも価値が高いと思います。
どのExcelVBAのレジェンドさんたちの本・ベストセラー本よりも先に買わなければならない数少ない本の1つです。初心者の上の方から中級者の方向けです。
絆創膏対応じゃない、王道に行ける可能性を高めてくれる本です。
↓中級者用の、日本の出版社が出しているもので「最も価値の高い一冊のひとつ」はこちら
『入門レベルでは決して足りない実務に必須のスキルとは ExcelVBA 実戦のための技術』
この本も、すぐには理解できなくても、VBAに対する理解が深まるにつれ、なんども読み返すたびに、重要性が増す本ですので、買って絶対に損のない価値の高い本です。
理解のし間違いをしやすい箇所についてや、クラスモジュール(オブジェクトの自作)などがわかりやすいく書いてあります。
こちらも、どのExcelVBAのレジェンドさんたちの本・ベストセラー本よりも先に買わなければならない数少ない本の1つです。
絆創膏対応じゃない、王道の本です。
この本以外は、ピボットの本と、グラフのVBA操作について詳しい本、Microsoft Queryに詳しい本、SQL、ADO、DAO、の本、COMオートメーションに詳し本、を買ったほうがいいと思います。あとピボットをVBAで動かすことを教えてくれるサイトも。
ついでに他の、参考になる「絶対に買って損はない・むしろ買うべき」、「超」初心者本(内容は狭いけど、でもためになる「超」初心者のための本)、をご紹介しておきます。
『スラスラ読める Excel VBA ふりがなプログラミング (ふりがなプログラミングシリーズ)』
一般変数(一般の文字ベースのデータ)の処理の基礎とオブジェクト変数(オブジェクト)の処理の基礎にしっかり分けて構成・書かれている隠れた良書です。一般変数での処理に関する記述が多く、オブジェクト処理はセルとシートの操作くらいですが、「超」初心者にはとても良い本です。こちらも他の初心者本には書かれていない重要なことが結構書かれています。こちらも一語一句、全部覚えると下手な「なんちゃって中級者」よりはよっぽどか しっかりした土台が理解できるようになれると思います。
また、変数をすべてVariant型でやってしまってますが、「超」初心者向けなのであえてそうしています。(明示的に型を決める方法にも読み終えた後にチャレンジしてみてくださいと書いてあります。)これもどのレジェンドさんの本よりもいいです。この本も、「超」初心者の方なら、どのExcelVBAのレジェンドさんたちの本・ベストセラー本よりも先に買わなければならない数少ない本の1つです。前の本と不足分をおぎないあっています。
この本も、絆創膏対応じゃない、王道に行ける可能性を高めてくれる本です。
『図解! Excel VBAのツボとコツがゼッタイにわかる本 “超"入門編 』
「セルとシートの操作関連の超基礎だけ」、の話がほんとんどです。あと若干のエラー対策、構築のためのポイント、など、です。一般変数の話やステートメントの話などは無いに等しいです。でも、他の初心者本には書かれていない重要なことが結構書かれています。一語一句、全部覚えると下手な「なんちゃって中級者」よりはよっぽどか しっかりした土台が理解できるようになれると思います。
また、でも、「超」初心者の方なら、どのExcelVBAのレジェンドさんたちの本・ベストセラー本よりも先に買わなければならない数少ない本の1つです。次の本と不足分をおぎないあっています。
この本も絆創膏対応じゃない、王道に行ける可能性を高めてくれる本です。
↓参考2:ExcelVBAの基礎のマインドマップ的な相関図メモ(xlsxのZipダウンロード)(ダウンロードして解凍後、ファイルオープンしてから ↓ この図が表示されるまでが少し時間がかかるかもです。)
↑ この図をクリックすると、PDFが開きますが、すべての横書きテキストボックスで、文章のおわりが途切れてしまっています。また、拡大すると画像が荒すぎてまともに見えません。なので「大体わかればいい」というときなどにお使いください。
「Ctrl+マウスホイール回転」、で拡大すると、文字だけはきれいに見えます。
正式には(正常表示できるものとしては)、前述の、xlsxファイルのほうが見やすいので、そちらもダウンロードして見てみてください。
テキストボックス内の文の途切れもありませんし、図中の「変数に関する表」をもう少し詳しくしたシート「●変数と生データに関する一覧表_詳細」が2枚目に付いています。
基本、この図の「一語一句でも」、わからないところがあったら、絶対に中級には上がれません。自力でのエラー解決も難しいので それまでVBAの学習にかけた時間やお金もドブに捨てる可能性が大です。私はExcel自体のド素人なので図が間違っているかもしれませんが、そうでしたら、先生や先輩に、「わかるまで何百回でも」何がどう間違っているかを聞いてください。もちろん普通にわからないところも。
いつもどおり、話が逸れまくってすみません。
前述の「5つの機能」のうち、「階層構造(≒階層構造上下自由往来機能)」と「プロパティ」はどのオブジェクトも100%必ず・保有・内包していて、「メソッド」「イベント」「ユーザー入力値」は内包しているオブジェクトとそうでないオブジェクトとがあります。
(※なので、逆に言うと、「階層構造」と「プロパティ」を保持しているものは、プログラミング的には100%、「オブジェクトだ」と判断できることになります。)
なお、「階層構造」については、厳密に言うと「階層構造自体の中にオブジェクトが組み込まれている」というかたちなんですが、「階層構造の中でコントロールされるための ”応答機能” や、”階層構造の中を上下に自由に行き来する機能=今居るところから上位や下位のオブジェクトの機能を、新しい変数設定なしに流用できる機能” を保持・保有・内包している・・・」みたいに、少し強引ですが、そんなイメージで考えてみてください。
当サイトでは、何度もそう説明するのが少し面倒なので、それで便宜的に「階層構造も ”内包される機能の一つ”」としてお話してしまっています。(すみません。)
「オブジェクト」は、そのように、「機能・あるいは命令語句をも」を「最初から」「自らにすべて内包してしまっている」ため、ユーザー側としては、「それを引き出してあげて動かす・・・」というイメージの動かし方になります。
そして「オブジェクト変数」には、この「5つの機能を内包した ”オブジェクト” 」が「まるっと代入される」ので、だから、オブジェクト変数もオブジェクトと同様に、「内包された5つの機能」を引き出すことによって、動かすことができる・・・、と、そういうかたちになります。
同じ変数でも「普通の一般的な変数(文字ベースのデータを扱う変数)」のように、「命令語句たちが、すべて変数の外側に在って、外側から変数を動かす」、というパターンとは少し異なります。
「もともとオブジェクト変数(=代入したオブジェクト)の中に内包されている5つの機能を、リモコンで引き出して使ってあげる/動かしてあげる・・・」といった感じの操作イメージです。
だから何だ、ということはないのですが、でも「違い」を意識するだけでも、、
・「階層構造(≒階層構造上下自由往来機能)」
・「プロパティ」
・「メソッド」
・「イベント」
・「ユーザー入力値」
のことや、「オブジェクト変数」のことが、なんとなくですが、少しとらえやすくなる・頭の中で整理しやすくなる・・・のではないかと思います。
以上のことは、こちらに図としても、「イメージ」をまとめましたので、ご参考にしてください。
『一般的に、「プログラミング」とは、どんなプログラミング言語であっても、「変数」というものを思い通りに動かすことで「自動化を実現する」作業です。それは変わりません。
そしてVBAプログラミングの場合は、「変数」には大きくは「2種類」あります。
「一般的な変数」と「オブジェクト変数」の2つです』・・・
・・・というところを図で、「なんとなくのイメージ」でまとめてあります。
厳密には違うかもしれませんが、VBAを習い始めの時はこんなイメージでオブジェクトやオブジェクト変数、その他一般の変数をとらえても全然問題ありません。また、意外とこう捉えたほうが学習も進みやすいのではないかと思います。
また、「オブジェクト」や「階層構造」「プロパティ」「メソッド」「イベント」「ユーザー入力値」などの少しだけ具体的な説明もしてありますので、一度是非、ごらんになってみてください。
特に、VBAをかじったけど、いまいち、「オブジェクト変数についてがよくわからない」、という方には見ていただきたいです。
というわけで、繰り返しになりますが、「オブジェクト変数」とは、イメージ的には・・・、
通常の変数には文字列か数値やYes/Noなど(文字ベースの値)しか代入できませんが、
「オブジェクト変数」
には
「前述のような ”オブジェクト” が持つ ”5つの機能丸ごと” も含めて、オブジェクトそのもの」
を 代入できる。
・・・そんなイメージです。
で、実際に「オブジェクト変数」にオブジェクトを代入する、といった場合・・・、
どうなるのか?具体的には何ができるようになるのか?ということですが・・・、
「5つの機能」によって、これ以降に書いたようなことができるようになります。(ちょっと説明が下手ですみません。)
例えば、あるExcelファイルの中に、「静的な表-意外とわかりにくい」という長ったらしい・かつ・変な名前の「シート」が作ってあったとします。
で、そのシート丸ごとを、「Sht01」というオブジェクト変数に代入した・・・というようなケースを例にして考えてみます。
その場合は、次のようなことができます。
(01)「静的な表-意外とわかりにくい」という長ったらしい名前の「シート」丸ごとを、
プログラムの中では「Sht01」という短い「仮名」で書けることになります。
プログラムがすっきりとします。
(02)「静的な表-意外とわかりにくい」という名前の「シート」丸ごとを
プログラムの中では「Sht01」という「オブジェクト」として「操作」、
できるようになります。
プログラムの中で「Sht01」という「オブジェクト」として「動かす」ことができるようになります。
「シート」というオブジェクト(単一のWorkSheetオブジェクト)が保持・保有・内包する「5つの機能(前述を参照)」が、使えるようになる、という意味でもあります。
(03)「オブジェクト」の場合の「操作」とは「メソッド」という命令を使う、という意味でもあります。
普通の変数では、文字列か数値などを切ったり貼ったり集計したりの加工をすることしかできませんが、オブジェクト変数に対しては、「メソッド」というオブジェクト専用の命令が使えるようになります。
それで「オブジェクト」を「操作」「動かす」ことをします。
ちなみに、各「メソッド」たちは、特定のオブジェクトに特化・紐付いた命令たちです。
「メソッド」を使うと、オブジェクト(=プログラムとしては「オブジェクト変数」のこと)を
自由に「動かす」ことができるようになります。
(=オブジェクトの持つ、機能を利用する・動かす、といったことができます。)
「メソッド」はもともとは「オブジェクト」に対して紐付いているもの・紐付いている命令ですが、「オブジェクト変数」は、その「オブジェクト丸ごと」が「代入」されたものでありますゆえ、「仮名ではありますが」、「オブジェクトそのもの」です。(VBAプログラムコードの中では。)
なので、「オブジェクト変数」に対しても、そのまま(代入されたオブジェクトの持つ)「メソッドが使える」ということになります。
メソッドには
例えば「WorkSheetオブジェクト(単一ワークシート管理機能)」や「WorkSheetsオブジェクト(複数ワークシート管理機能)」というオブジェクトに対してなら、次のような専用のメソッド(命令)があります。(ここでは2者の共通のメソッドをご紹介しています。)
・Move after:=Worksheets("Sheet3")(「Sheet3」シートの後ろに移動しろ)
・PrintOut(印刷しろ)
・PrintPreview(印刷プレビューを表示しろ)
・Select(シートを選択しろ)
・Copy(シート内のすべてのセルの値や機能はもちろん、
シートの持つ機能や設定値等々丸ごと全てをコピーしろ)
・Delete(シートを削除しろ)
※ すべてのオブジェクトに、同じメソッドが紐付いているわけではありません。
※ オブジェクトごとに、使えるメソッドが・紐付いているメソッドが異なります。
「単一ワークシート管理機能(WorkSheetオブジェクト)」と
「複数ワークシート管理機能(WorkSheetsオブジェクト)」には
(=WorkSheetsコレクションオブジェクト。「s」に注目。)
上記のような共通のメソッドもありますが、
相容れないそれぞれ独自のメソッドのほうが多いです。
例えば「静的な表-意外とわかりにくい」という名前の「シート」丸ごとを「Sht01」という「オブジェクト変数に代入した場合、プログラムの中では以下のように書くことができます。(もし見づらかったら、ご自分で表にでもしてみてください。)
・Sht01.Move after:=Worksheets("Sheet3")
(「静的な表-意外とわかりにくい」シートを
「Sheet3」シートの後ろに移動しろ)
・Sht01.PrintOut
(「静的な表-意外とわかりにくい」シートを印刷しろ)
・Sht01.PrintPreview
(「静的な表-意外とわかりにくい」シートの印刷プレビューを表示しろ)
・Sht01.Select
(「静的な表-意外とわかりにくい」シートを選択しろ)
・Sht01.Copy
(「静的な表-意外とわかりにくい」シート内の
すべてのセルの値や機能はもちろん、
シートの持つ機能や設定値等々丸ごと全てをコピーしろ)
・Delete(「静的な表-意外とわかりにくい」シートを削除しろ)
(04)「オブジェクト(=オブジェクト変数)」が扱えてオブジェクトが動かせるようになると、 各オブジェクトの「プロパティ(性質・特性・各種設定)」の「設定値」や「入力値」などが取得できるようになります。
それらを取得することで、
例えば、「もしこのオブジェクトのこの設定値がこの値の場合は、こういう風に動け」・・・
・・・という形の命令を書くことができます。
つまり、オブジェクトに対して、「おいおまえ、ロボットのように動け」と命令できるわけです。
普通の変数の場合は、数値や文字列を切ったり貼ったり集計したりができるくらいで、
「ロボットのように動け」と命令できません。
できたとしも、実際に自動的にロボットのように動くわけでもありません。
でもオブジェクト変数があるおかげで、逆にそれがとてもやりやすくなります。
(05)「オブジェクト変数」を使うことで、「オブジェクト」を「まるでロボットであるかのように」動かすことができるようになります。
「メソッド」や「ステートメント」といった命令語たちや
「プロパティ」と呼ばれるオブジェクトの持つ各種設定値を使って。
また、「イベント」を使えば、何らかのタイミングでオブジェクトを
自動的に動かすこともできます。
(06)「シートがもつ機能の設定値」・・・、例えば「セルの値」「数式」などを取得することが簡単になります。
例えば、「静的な表-意外とわかりにくい」という名前のシートの、A1セルの数式を取得したい場合は、
「Worksheets("静的な表-意外とわかりにくい").Range("A1").Formula」
と書くことで取得ができます。
が、その「静的な表-意外とわかりにくい」というシートの機能丸ごとを
オブジェクトとして、「Sht01」というオブジェクト変数に代入してしまうと、
「Sht01.Range("A1").Formula」
と短く書いても同じ数式が取得できます。
ついでに言うと、「セルA1」を表す「Range("A1")」もオブジェクト変数に代入してしまうことができます。
その場合、例えば「Sht01」のA1セル・・・、
・・・「A1セル」自体はVBAでは「Range("A1")」と書き表しますが、「Sht01のA1セル」という意味合いだと、(前述では)「Sht01.Range("A1")」と書きました。
で、それをまるっと、例えば「CelA1」というオブジェクト変数に代入することもできます。(実際にはそこまでやってしまうと後が面倒になるのでやりませんが、短く書ける、ということの例として挙げました。)
そしてその場合(例えば「Formula」という数式の操作なら)、
「Worksheets("静的な表-意外とわかりにくい").Range("A1").Formula」
と長ったらしく書かなくても、
「CelA1.Formula」
と、とても短く書くことができます。
「単一オブジェクトだけでなく、”階層構造丸ごと”を、階層が何段階あったとしても、1つのオブジェクト変数に代入することもできてしまう。とても便利。」・・・ということになります。
また、この場合、メソッドのことをからめて言うと、例えば「Copy(=コピーしろ)」というメソッド(命令)を使うことで、
「”静的な表-意外とわかりにくい”というシートのセルA1をコピーしろ」というプログラムを
「Worksheets("静的な表-意外とわかりにくい").Range("A1").copy」
と書くのではなく、
「CelA1.Copy」
と、短く書けてしまいます。
そして、このコピーの場合、セルの値だけではなく、数式もセルの色も書式設定も、つまり、セルのもつ機能も各種設定値も、そのすべてがコピーされます。
例えば、A1セルに色を付けてから「CelA1.Copy」とやったのち、その直後にどこか適当なセルに「貼り付け」をすると、セルの値だけではなく、数式もセル色も文字色も貼りつきます。
それを見ても、オブジェクト変数にはオブジェクトの入力値だけではなく、「すべての機能や設定値(5つの機能)が代入されている」、となんとなくイメージできるのではないでしょうか?
(07) なお、オブジェクト変数にオブジェクトを代入するには「Set」という命令を使います(それが必要です)。
「プログラム」というものには、英語の文法のように「構文」があるのですが、
オブジェクト変数にオブジェクトを代入する場合のその「構文」としては、
「Set オブジェクト変数名 = ××××××」という形になります。
普通の変数の場合は「=」記号だけで数値や文字列の代入ができますが、
オブジェクト変数の場合は、
「Set オブジェクト変数名 = ××××××」という構文が必要になります。
前述の各例も、(省略してしまいましたが)本当は、
「Set オブジェクト変数名 = ××××××」という命令を書くことが前提となっています。
「××××××」は、「オブジェクト」を表す参照式です。(=「オブジェクト式」です。)
例えばよくあるのは、「Range("A1")」とか、「Cells(1,1)」とか、「Worksheets(1)」などがそれです。
ちなみにですが、「Set オブジェクト変数名 = ×××××× 」の形は、「オブジェクトを返す自作関数」でも使い方が似ていて・・・、その自作関数の中で・・・、
「Set 自作関数名(=プロシージャ名) = 何らかのオブジェクト式 」
・・・といった書き方をすると、ユーザー側にオブジェクトを返すことができます。(「何らかのオブジェクト式」は、もちろん複数の階層の階層構造を持つものでもOKです。)
そのように自作関数を使って取得したオブジェクトも・・・、
「Set オブジェクト変数名 = 自作関数(引数)」
・・・という形で、オブジェクト変数に代入することができます。
同様に、「××××××」の部分は、「オブジェクト式」以外に、「Excelにもとから組み込まれている ”オブジェクトを返す関数やメソッド” 」などである場合も多いです。
例えば「CreateObject」関数とか、「GetObject」関数、「Object.Open」メソッドなどです。
その際は・・・、
「Set オブジェクト変数名 = Excel組み込みVBA関数(引数)」
「Set オブジェクト変数名 = メソッド(引数)」
といったような書き方になります。
例えば「CreateObject("Word.Application")」と書くと、CreateObject関数は、Wordの「(見た目的に)のっぺらぼう状態のガワの部分」をオブジェクトとして、ユーザーに返してくれます(返してくれる=取得してくれる)。
※参考記事
『Access2000VBA・Excel2000VBA独学~★★★超重要!!!「実際の機能や画面等々」と「VBAオブジェクト」との対応。例えば「Application」って何?Workbookとの関係は?』
『Access2000VBA・Excel2000VBA独学~用語:”目に見える”「メソッド・プロパティ・列挙(=Enum)・定数(=Const)」と右クリックメニューの画面の関係について~』
もう少し詳しく言うと、「見た目的に、中身(新規ファイルの白紙)の抜け落ちた、リボン(もしくはメニューバー)だけが表示された ”アプリケーションウィンドウ ”」を、ユーザーに返してくれます。
この場合、のっぺらぼうのWordのアプリケーションウィンドウもオブジェクトの一つ・・・ということになります。
つまり・・・、関数が、オブジェクトをユーザーに返してくれる(=取得して戻してくれる=渡してくれる)ので、それをそのままオブジェクト変数に、Set を使って放り込んであげれば、そのオブジェクト変数についても、(オブジェクト式を代入した場合と同じように) オブジェクト操作ができるようになる・・・ということです。
ちなみにですが、「CreateObject」関数でWordやAccessのガワ(アプリケーションウィンドウのみの状態)を呼び出すと、VBE(VisuaBasicEdior)でWordやAccessに対して参照設定をしなくても、COMオートメーションにて、ExcelからWordやAccessを操作できるようになります。
なお、「CreateObject」関数でガワを呼び出してSet した場合、既定では「非表示状態」で呼び出されるので、多くの場合はそのあとに、「非表示を解除して明示的に表示させるプログラムコード」を書きます。
(「オブジェクト変数.Visible = True 」みたいなやつです。)
ちなみにですが、例えばExcelの「Workbooks.Open 」メソッドは、指定したパスのブックを開きつつ、開いたブックをオブジェクトとして返してもくれます。なので、この場合も、帰ってきたオブジェクトしてのブックを、オブジェクト変数に代入して、オブジェクト操作することが可能となります。
例えば・・・、
「Set オブジェクト変数名 = Application.Workbooks.Open("Excelファイルのフルパス")」
・・・みたいな感じで書くと、フルパスで指定したブックを開きつつ、そのブックを「オブジェクト」としてVBA操作できるようになります。
(08) オブジェクトを扱う「共用部品」「関数」などを作るときに大変作りやすくなります。
これは実際にプログラミングしながらじゃないとなかなか理解できないので、ここでの説明は割愛させていただきます。
「へー、そういうことができるんだあ~」、くらいに思っててくだされば十分です。
(09)オブジェクトやオブジェクト変数を、「配列」のように扱える「コレクション」というオブジェクト・機能も使えるようになります。
「コレクション」は「同じ種類・あるいは異なる種類の、”単一オブジェクトたち” 」の「集合体」です。
「コレクション」という機能(これもオブジェクトの一種なのですが)を利用すると、オブジェクトを、「配列」のような感じで扱えるようになります。
(配列とは→例えば、100個、200個という似た種類の変数をまとめて一括処理できるようにするような仕組みです。Webで検索してみてください。)
例えば、ワークシートの場合で、ワークシートが左から
「Sheet1」
「Sheet2」
「Sheet3」
と並んでいたとします。
その場合に、すべてのワークシートに何らかの一括処理をしたい場合、
Worksheets("Sheet1")、
Worksheets("Sheet2")、
Worksheets("Sheet3")
・
・
・
と、ワークシートを「名前で」指定して、プログラムを書いて、逐一処理する方法もありますが、
それとは別に
Worksheets(1)、
Worksheets(2)、
Worksheets(3)
・
・
・
と、ワークシートの名前ではなく、「配列」の「要素番号」のように書き替えて、一括処理する方法もあります。
1、2、3、は、ワークシートの左からの並び順どおりです。
一番左のワークシートが「Sheet1」だったら、Worksheets(1)は「Sheet1」のことを指し、
左から2番目のシートが「Sheet2」だったら、Worksheets(2)は「Sheet2」のことを指し、
左から3番目のシートが「Sheet3」だったら、Worksheets(3)は「Sheet2」のことを指し、
・
・
・
という風になります。
もし、「静的な表-意外とわかりにくい」という名前のシートが一番左に存在したら、
Worksheets(1)は「静的な表-意外とわかりにくい」というシートのことを指す・・・
という意味になります。
この複数のシートの集合体を「シートのコレクション(WorkSheetsコレクション)」という風に呼んだりします。
誤解しないようにしてほしいのですが、実は、Worksheets("Sheet1")という書き方も、Worksheets(1)という書き方も、両方とも(「プロパティ」という機能を使いつつ同時に)、「コレクション」という機能を経由しているようです。(ヘルプを読むとそんなイメージに見えます。)
ただ、そのうち、Worksheets(1)という書き方のほうが、ちょっと「配列を扱うときに似てる・・・」というだけの話なので、かえって混乱を招いてしまったかもしれませんね。
ごめんなさい。
でも、これも「へー、そういうことができるんだあー」くらいに思っておいてください。
なお、オブジェクトをそのオブジェクトにつけられた名前ではなく、要素番号で書き表せると、「ループ処理」というかたちで一括処理がより簡単になります。
例えば、Excelファイルの中にシートが20枚あったっとしてその20枚のシートに同じ処理をしたい場合、各シート名を使ってプログラムを書くと、
Worksheets("Sheet1")、
Worksheets("Sheet2")、
Worksheets("Sheet3")
・
・
・
という形で、「20枚分×処理内容」、という行数が必要です。
でも、シート名ではなくて、オブジェクトの要素数で処理できるとなると(変数設定などは省略)次のように「ループ処理」という形でプログラムを書くことができるようになります。
例えば、
i=1 '一応初期化
For i = 1 To Worksheets.Count
'コメント:処理内容
Debug.Print Worksheets(i).name
Debug.Print Worksheets(i).AutoFilterMode
Debug.Print Worksheets(i).CodeName
Next i
と書いたり、
For Each sheeets_hairetu In Worksheets
'コメント:処理内容
Debug.Print sheeets_hairetu.name
Debug.Print sheeets_hairetu.AutoFilterMode
Debug.Print sheeets_hairetu.CodeName
Next
と書くだけで20枚分のシートへの同じ処理ができます。
(もし仮に100枚のシートがあっても、このプログラムだけで処理できてしまいます。)
このとき、もし処理内容が3行ほどあったとしたら、シート名で処理すると、最低限、「シート20枚分×3行=60行」のプログラムが必要です。
でも上記のプログラム例のように、シート名ではなく要素番号を使ってループ処理でやれれば、「For i ・・・Worksheets.Count」を使う方法にしても 「For Each」を使う方法にしても、 6、7行ほどで書けてしまいます。
60行必要なところが、7行で終わるのです。
書く労力もすくなくなりますし、何より、見やすくなって目にも優しいです。
記述ミスも発見しやすくなります。
また、(前述もしましたが)、実は「コレクション」も「オブジェクトの一種」なので、オブジェクト変数に代入することができます。
以下のように書けば、今開いているExcelファイルの「WorkSheetsコレクション」自体を「オブジェクト変数」に代入したことになります。そして、各シートを要素番号で処理できるようになります。(要素番号=インデックス番号)
Dim WsClctn As Object
Set WsClctn = ActiveWorkbook.Worksheets
Debug.Print WsClctn(1).Name
この例では、今開いているExcelファイルの「WsClctn(1).Name」・・・、つまり今開いているExcelファイルの「WorkSheetsコレクション」の中の「一番最初のシート=一番左側に位置するシート」の名前・・・をVBEの、イミディエイトウィンドウに表示してくれます。
また、ちょっと脱線しますが、例えば「Worksheets.Count」は「ファイル内のシートの数」という意味なんですが、これも、「コレクション」という仕組みがあるので数を簡単に数えられるようになっています。
コレクションという仕組みがなかったら、たぶん、やたら長いプログラムを書いて、シートの数を求めないといけなくなると思うのですが、「コレクション」という仕組みがあるために、「Worksheets.Count」というとっても短い単語で求めることができてしまいます。
これは「オブジェクト」という概念があるからできることです。
ちょっと脱線しましたし、イメージしにくいかも、とも思いますが、「オブジェクト変数」は「オブジェクトやコレクションを扱いやすくしてくれるもの」ということも言えると思います。
前項の(08) のところで『オブジェクトを扱う「共用部品」「関数」などを作るときに大変作りやすくなります。』と書きましたが、それは、このコレクションの機能(コレクションオブジェクト」にも言えることで、コレクションのおかげでも、本当に共用部品が作りやすくなります。
(10) オブジェクト変数を定義(宣言)するとき、迷ったら「 As Object」を書けば当面は大丈夫。(複雑・厳密なプログラムでなければ)
「Dim WsClctn As Worksheets」などのように書いたとき、実行したらエラーが出てしまうような場合は、
「Dim WsClctn As Object」と書いてしまうとエラーが出なくなることがあります。
このように、「As ・・・・」 のところで何を指定したらいいかわからないときは、わかるまで、「なんでもかんでも Object でいい」という感じで書いてしまってもよいと思います。
(正しい記述を見つける時間がないときはとくに。)
ただ、複雑・厳密なプログラムでは「なんでもかんでも Object でいい」というある意味・安易な考えが重大なトラブルを生む原因にもなりかねないので、注意して、Q&Aサイトで聞くなどして、できるだけ正しい記述方法に直すようにしてください。
※厳密に、「As Object」ではなく ちゃんとしたオブジェクト名を使いたい、という場合は、変数宣言をいったん「Object」で書いておいて、「Stop」命令も書いてわざと中断させ、VBEの「ローカルウィンドウ」というものを表示させると、その中に、「Object」が、厳密にはいったい何なのか?が書かれていて判明します。
判明したら、変数宣言の「As Object」を、厳密なほうのオブジェクト名に書き換えます。
★ 要注意!Excelの面倒くさくて理解しづらい困ったコード記述仕様!
(ExcelとAccessの「オブジェクトの取得方法」についての違い。)
※ この項のことを知った重要なWeb記事
「オブジェクト名.プロパティ」という解説はウソですよ
Cellsオブジェクトは存在しない
プロパティは2種類ある
Excelマクロ入門書籍をたくさん見て驚いた
オブジェクトブラウザーに表示されるアイコンの意味
『Excel VBA講座 オブジェクト式解説編』について
VBAのコレクションとは
Application(上位オブジェクトへの参照)を省略できるプロパティとは
VBAでアクティブシートの名前を取得する-ActiveSheet.Name
オブジェクトブラウザでプロシージャを簡単に見つける
VBAから使えるワークシート関数をオブジェクトブラウザで調べる
RangeオブジェクトとRangeを返すプロパティ
シートやブックを越えたRangeオブジェクト取得
Range,Cellsの組み合わせでシート指定
上記サイトによると、Accessはコレクション(複数オブジェクトの集合体)が入り口で、単一オブジェクトを取得する(=単一オブジェクトを操作できるようにする)ことが多いそうです。(最近、これらのサイトを見て知りました。)
例えば、「一番最初に開いたフォーム」を取得する(操作できるようにする)には、「Forms」というコレクションが入り口です。(コレクション=コレクションオブジェクト=コレクションという種類のオブジェクト・・・、つまり機能・ツールです。)
Accessの場合は、開いたフォームがフォームビューでもデザインビューでも、
「Forms(0)」と書けば1番最初に開いたフォーム
「Forms(1)」と書けば2番めに開いたフォーム
「Forms(2)」と書けば3番めに開いたフォーム
という感じです。
もう一度書きますが、Accessの「Forms」は「コレクション」です。
※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 ×××× 」と書いてあります。
つまり、「コレクション=複数のオブジェクトの集合体」の中から「単一のオブジェクト」を選べるので自然な感じです。
参考:Accessのオブジェクトがもつメソッドやプロパティ、イベントを調べる
『オブジェクト モデル (Access VBA リファレンス)』
それに対して、Excelは、ちょっと面倒くさくて、「プロパティ」が入り口となって、単一オブジェクトを取得するような恰好が多いです。
コレクションが入り口じゃありません。
コレクションが入り口となって、単一オブジェクトを選ぶ場面が少ないっぽいです。
しかも、そのプロパティの名前が、「コレクション名」と同じだったりするので(つまり、プロパティ名と同名のコレクションオブジェクトが存在するので)、さらにわけがわからなくなりがちです。(※2019/05/14追記:これはAccessも同じでした。ヘルプに書いてないので「コレクション経由」があると勝手に思い込んでしまいました。本当に申し訳ございません。)
プロパティ経由でコレクションを呼び出す、あるいは、プロパティ経由でないとコレクションを呼び出せない、というシーンがとても多いです。
すごくめんどくさい!!!
マイクロソフトさんがなんでExcelをそんな面倒くさい仕様にしたのかわかりませんが、いずれにしても、Excelの「まともな講師さん」によると、『ここでつまづく初心者の方が非常に多い=「オブジェクトそのもの」やその構造を理解している人が少ない』、だそうです。
Excelの場合、例えば、
・「単一のWorksheetオブジェクト」を取得するには、
・「Worksheetsコレクションオブジェクト」直接からではなくて、
・一旦、(単一のWorksheetオブジェクトの1階層上位の)「Workbookオブジェクト」「の」、「Worksheetsプロパティ」を経るなどして、
・そこを「入り口」に、おそらく「Worksheetsコレクションオブジェクト」(ヘルプによるともしかしたら Sheets コレクションかも)へアクセスして、
・そこから「単一のWorksheetオブジェクト」を取得します(=Pickup=取り出します)。
・それらを入り口にしてしか、「単一のWorksheetオブジェクト」を取得することができない仕様になっています。
Rangeオブジェクトの場合は、Rangeオブジェクト自体がコレクション的な性質を持っているようです。(For Each 文 が、Rangeオブジェクトの範囲内のすべての単一セルに対して使えるので。)
「1つのセル」という、「ある意味単一のオブジェクト」が複数集まったものが、
「Range」という、つまり、「選択範囲」を意味する・「ある意味コレクション的な」オブジェクトである・・・
というイメージです。
単一のRangeオブジェクトを取得するには、コレクションからではなくて、(Rangeの上位の)WorksheetオブジェクトやRangeオブジェクトの、「RangeプロパティやCellsプロパティ」から取得します。
それらを入り口にしてしか、Rangeオブジェクトを取得することができない仕様になっています。
なお、Worksheetオブジェクトの「RangeプロパティやCellsプロパティ」から取得すると、絶対的な感じで取得でき、
Rangeオブジェクトの、「RangeプロパティやCellsプロパティ」から取得すると、相対的な感じで取得できます。例えば、ActiveWorkbook.Activesheet.Range("B5:D7").Range("A1")、と書くと、B5
セルを起点=A1セルとみなせます。そういうRangeの取得ができます。
親のオブジェクトが変わると、動きも少し変わる、ということのようです。
(※2019/05/14追記:Accessの場合も同様でした。大変申し訳ございませんでした。)
※参考記事
『用語:~Excel2000~RangeプロパティでのRangeオブジェクトの取得と、Cellsプロパティでのそれとの違いについて』
たとえば
Range("A1")
と書かれたときは、この「Range」は
「Rangeオブジェクト」のオブジェクト名としての「Range」ではなくて、
「WorksheetオブジェクトのRangeプロパティ」、つまり、プロパティ名としての「Range」です。(つまり「Range」という、” オブジェクト名ではなくプロパティ名 ” です・・・、ということです。)
しかも、RangeオブジェクトにもRangeプロパティなんてものがあって、それが「オブジェクトになる」というのですから、さいしょのうちは頭がこんがらがってしまいます。
でも、「RangeオブジェクトとRangeプロパティの違い」や、「Excelではオブジェクトを取得するのにコレクションではなくプロパティを使う」、といったことなどを理解できないと、結局、ExcelVBAのヘルプが読めません。
また、Webのマイクロソフトの情報も理解できません。
私らど素人にしてみたら、とても困った仕様にしてくれたものです。
マイクロソフトさんのVBAのサイトの『Worksheet オブジェクト (Excel)』によると、次のように書かれています。
『
例
単体の Worksheet オブジェクトを取得するには、 Worksheets ( index ) プロパティを使用します。引数 index には、ワークシートのインデックス番号または名前を指定します。次の使用例は、作業中のブックのワークシート 1 を非表示にします。
Worksheets(1).Visible = False
』
つまり、ここに書いてある「Worksheets」は「Worksheetsコレクションオブジェクト」ではなく、「Worksheetsプロパティだ」ということだそうです。
意味、わかりますか?
これを理解できないと、ExcelVBAの高度な内容への上達はなかなか見込めません。
(でないと、自分でヘルプやマイクロソフトの情報などを読めないままだから。)
AccessならForms(0)のFormsはコレクションオブジェクトなのでわかりやすいんですけど・・・
※前述のとおり、間違いでした。大変申し訳ございません。
なお、Worksheets プロパティには、
Application.Worksheets プロパティ
Workbook.Worksheets プロパティ
の2つがあるあらしく、いずれも、「オブジェクト修飾子を指定しないコードを使用すると、作業中のブックのすべてのワークシートが返されます。」と書いてあります。
つまり、「Application.」とか「Workbook.」と書かなくても単一のワークシートをオブジェクトとして取得でき、いずれも「作業中のブックのすべてのワークシート」という「Worksheetsコレクションオブジェクト」のようなものが返されます。
なので、0とか1とか、名前とか、を指定すると、操作対象のワークシートを1つに決め打ちできる、ということのようです。
このように、Excelは「単一のオブジェクト」をAccessのような「コレクション経由」ではなくて何らかの「プロパティ経由」で取得する、というケースがとても多いです。
ここはご注意ください。
コードの書き方の基本としては、ExcelVBAの場合は、
「上位のオブジェクト名.オブジェクト名.プロパティ名・・・」
(あるいは、コレクションオブジェクト名.プロパティ名・・・)
ではなくて
「上位のオブジェクト名.プロパティ名のみ(オブジェクト取得兼務).必要に応じてさらにプロパティ名・・・」
(もとから、オブジェクトやコレクションをダイレクトには使えない)
という場合が多い、ということです。
Excelの場合、下位のオブジェクトを取得するのにも「プロパティ経由」ということがあります。
例えば「オブジェクト.オブジェクト.オブジェクト.プロパティ・・・」みたいに書きたいときの2つめや3つめのオブジェクトです。
例えば
「Worksheets("Sheet1").PageSetup.Orientation = xlLandscape 」
と書いたとき、「Worksheets("Sheet1")」がまずプロパティ記述ですよね。
で、その次の「PageSetup」もプロパティ記述だそうです。
『PageSetup オブジェクト (Excel)』によると、「PageSetupオブジェクト」を取得するための「PageSetupプロパティ」だそうです。
ほんとめんどくさい!
Accessは素直に
「オブジェクト名.プロパティ名・・・」
(あるいは、コレクションオブジェクト名.プロパティ名・・・)
あるいは
「オブジェクト名.オブジェクト名.プロパティ名・・・」
というコードの書き方が多いです。
もうすこし範囲をせばめて言うと・・・、
Accessの場合は、「単一のオブジェクト」を書き表す場合に、
「オブジェクト名」
もしくは
「コレクションオブジェクト名(インデックス)」
と書くことが多いのに対し、
Excelの場合は、
「取得したいオブジェクトが持つプロパティ名(インデックスやプロパティの引数)」
と書くことが多い(コレクションは使わない)、
・・・ということです。
(※Accessの場合も、ApplicationプロパティやCurrentProject プロパティ、CodeProjectプロパティなどのように、プロパティ経由でオブジェクト取得するものもありますが、よく使うFormやPeportなどはコレクション経由でのオブジェクト取得なのでわかりやすいです。)
プロパティのヘルプに「××を表す ×× コレクションを返します。」と書かれていれば、インデックス、つまり、番号や名前を指定します。あるいは、オブジェクト変数に代入したい場合などは、ケースによってはインデックスは書きません。
「××を表す ×× コレクションを返します。」と書かれていなければ、ヘルプの内容通りにプロパティの引数を書きます。
ところで、Excelでなぜコレクションを使わなくても単一オブジェクトが取得できるのか?ということですが、 僕の勝手な推測ですけど、たぶんマイクロソフトさんのExcelVBAのチームが、「コレクションを指定しなくても、プロパティを指定しただけでコレクションが取得できるようにしよう!そのほうがだらだら長ったらしいコードにならなくて済むじゃん!!」ということなんではないかな?と推測しています。
あるいは、Rangeなどはいろんな選択の状況があるので、あえてそうしたのか・・・
いずれにしましても、たぶん、ソフトを作る側の都合だと思いますし、素人エンドユーザーが「なんでこんなわかりにくい、面倒くさい記述仕様にした?」と考えてみたところで、相手は「このほうが理解しやすい」と思ってやってると思いますので、そんなことをいちいち気にしても精神衛生上よくないですから、考えないほうがいいと思います。
いずれにしても、Excelは、オブジェクトを使った共用部品を作りたいときなどに、Accessのように素直じゃないかもしれないのでご注意ください。
ちなみにですが、どうやら、Wordもこの「プロパティ経由でオブジェクト(オブジェクトへの参照=オブジェクトの参照式)を取得する」というパターンが多いらしいです。
(※前述のとおり、Accessもでした。申し訳ございませんでした。)
ExcelのRangeに相当する、Wordの「Selection オブジェクト」の取得については、ヘルプに「Selection プロパティを使用して Selection オブジェクトを取得します。」と載っていましたので・・・。
※関連記事
Access2000VBA・Excel2000VBA独学~VBAプログラミングとはどんなプログラミング方式なのか?(簡易版)
※ 参考サイト
以下のサイトの画面左側の「オブジェクト モデル」のところをクリックすると、各オブジェクト名が出てきますので、それをクリックすると、右側に「プロパティ」や「メソッド」が出てきます。
イベントをもつオブジェクトなら、イベントも表示されます。
Excelのオブジェクトがもつメソッドやプロパティ、イベントを調べる
『オブジェクト モデル (Excel VBA リファレンス)』
Accessのオブジェクトがもつメソッドやプロパティ、イベントを調べる
『オブジェクト モデル (Access VBA リファレンス)』
Wordのオブジェクトがもつメソッドやプロパティ、イベントを調べる
『オブジェクト モデル (Word VBA リファレンス)』
Outlookのオブジェクトがもつメソッドやプロパティ、イベントを調べる
『オブジェクト モデル (Outlook VBA リファレンス)』
PowerPointのオブジェクトがもつメソッドやプロパティ、イベントを調べる
『オブジェクト モデル (PowerPoint VBA リファレンス)』
ADOやDAO
『Access デスクトップ データベース リファレンス』
『Microsoft データ アクセス オブジェクト (DAO)リファレンス』
- 投稿タグ
- ExcelVBA, Excel連携VBA, パソコンでの自動化, マクロ, 自動化