Access2000VBA・Excel2000VBA独学~初心者の方へ:オブジェクトのオブジェクト変数への代入について、どう考えたらとっつきやすくなるか?~
※まだ書きかけです。すみません。
※間違ってたらすみません。
※メモ書きなので、自分でも意味不明な箇所も多いです。ごめんなさい。
★ 結論
結論から言いますと、オブジェクト変数へのオブジェクト(=オブジェクト式)の代入については・・・、
『長いオブジェクト式を短い単語に置きかえて見やすく書くことができる。そしてその際(代入の際)には「Set」という単語が必要。まずはその機能のことだけを覚えればいい。
あとの 各オブジェクトの中に含まれる「階層構造上下自由往来機能や上下階層の機能流用機能、プロパティ・メソッド・イベント・ユーザー入力値」といったより詳細な機能たちのことは、徐々に覚えればいい。
ただし、いつかは「一般的によく使われる機能」は覚えないとダメ。丸暗記はできなくてもいいので、Webやヘルプで検索・ヒットした時に意味が分かる程度に。
それらの機能(命令)はすべてオブジェクト=オブジェクト式の中に含まれるので、それらの機能(命令)を内側から引き出して使うことになる。』
・・・という感じで覚えたらよいのではないか?と思いました。
最初からすべてを理解できる人はそうすればいいですが、それが難しい場合のほうが多いので、最初のうちは
『オブジェクトの場合の代入処理には、Setという単語が必要』ということと、
『長いオブジェクト式を短い単語に置きかえて見やすく書くことができる。』ということだけを知っておけばいいなと思いました。
もう少し具体的には以下のように学んでいったらいいのかも?と思いました。
(a)オブジェクトとは「目に見える/見えない/大きい/小さい」にかかわらず、「3D的、立体的」な、「ユニット・複数の機能の複合体・パーツ・部品」、「ある意味、Excelという大きな工場で働くミニミニロボットたち」のことで、VBAコード上としては、「オブジェクト式」のことを意味します。
※絶対にこちらも読んでおいてください!! ↓↓↓
★★★★★★★★★★★★★★★★ 超重要!!必読!!ExcelVBAが上達するかどうかの最初の分かれ道!オブジェクトとオブジェクト式について~★★★★★★★★★★★★★★★★
この(a)の項をもう少し詳しく書いた記事です。
(b)VBAの習い始めのころは、
『オブジェクト変数へオブジェクト(=オブジェクト式)を代入する』とは、
「長いオブジェクト式を短く書ける」ということだけを覚えるだけでいい。
そして代入するときには、(一般変数=文字ベースの値を代入するための変数)の時とは違い、冒頭に「Set」が必要。
(c)VBAの習い始めのころは、
『 オブジェクトの中には、
・階層構造上下自由往来機能や
・上下階層の機能流用機能、
・プロパティ
・メソッド
・イベント
・ユーザー入力値、
といった機能=あらかじめ紐付けされた命令たちがすべて含まれている』、
ということはさほど意識せず、
「オブジェクト式を短い単語におきかえて扱える」ということや、
例えばセルというオブジェクトなら、
「ユーザーの入力値については、Valueプロパティというもので扱う」
「Valueプロパティは多くの場合は省略できるが、省略するとエラーや誤作動を起こすケースもあるのでその場合は省略しないようにしっかり書く」
ということだけを覚えればいい。
(d)学びが進むにつれて、
それらの「オブジェクトに含まれる機能=命令たち」も、「オブジェクト変数に一緒に代入される」ということがイメージできて、
かつ、「オブジェクトの操作」とは、それらの内部に含まれる機能=命令たちを、内側から引き出してあげつつ、外側からステートメントや列挙・定数などで動かす・・・ということが、実感としてイメージできるようになれればいい。
(実際にはオブジェクト変数に代入されるのはオブジェクトへの参照=オブジェクトへのショートカットアイコンのようなもの、というイメージで居ればOKですが)
★ 説明
一般変数の「生データ」は文字列、数値、日付データ、論理値(TrueやFalseなどの2値)などがあります。
それに対して、オブジェクト変数の場合の「生データ」に相当するものは「オブジェクト式」です。
例えば以下のようなものが「オブジェクト式」です。(=オブジェクト変数に代入されるもの)
(01) Application.Workbooks("Book1.xlsx")
(02) Application.Workbooks("Book1.xlsx").Worksheets("Sheet1")
(03) Application.Workbooks("Book1.xlsx").Worksheets("Sheet1").PivotTables(1)
(04) Application.Workbooks(1).Worksheets(1)
(05) Application.Workbooks(1).Worksheets(1).PivotTables(1)
(06) VBAProject.Sheet1.PivotTables(1)
(07) Application.Workbooks("Book1.xlsx").Worksheets("Sheet1").Range("A1")
(08) Application.Workbooks(1).Worksheets("Sheet1").Range("A1")
(09) Application.Workbooks(1).Worksheets(2).Range("A1")
(10) VBAProject.Sheet1.Range("A1")
※「Application.」や「Item.」は、省略されることが多いです。
省略してもほとんどのシチュエーションで事故にならないためです。
(稀になる場合は、省略せずに書きます。)
それぞれ上から・・・
(01) 「Book1.xlsx」というブック
(02) 「Book1.xlsx」というブックの「Sheet1」というワークシート
(03) 「Book1.xlsx」というブックの「Sheet1」というワークシート上の1つ目に作ったピボットテーブル
(04) 1つ目のブックの一番左から数えて1つ目のワークシート
(05) 1つ目のブックの一番左から数えて1つ目のワークシート上の1つ目に作ったピボットテーブル
(06) 「Sheet1」というオブジェクト名(コード名)のワークシート上の1つ目に作ったピボットテーブル
(07) 「Book1.xlsx」というブックの「Sheet1」というワークシート上の「A1」セル
(08) 1つ目のブックの「Sheet1」というワークシート上の「A1」セル
(09) 1つ目のブックの、一番左から数えて2つ目のワークシート上の「A1」セル
(10) 「Sheet1」というオブジェクト名(コード名)のワークシート上の「A1」セル
という意味です。
例えば、セルを表現するオブジェクト式として、
Application.Workbooks("Book1.xlsx").Worksheets("Sheet1").Range("A1")
と書くことがあります。
これは「Book1.xlsx」というブックの「Sheet1」というワークシート上の「A1」セル、という意味です。
これを例えば「o_RngA1Cell」という変数を作ったとしますと、そこに代入することができます。
代入のプログラムコードは以下のようになります。
Dim o_RngA1Cell As Range
Set o_RngA1Cell = Application.Workbooks("Book1.xlsx").Worksheets("Sheet1").Range("A1")
これ以降は、
Application.Workbooks("Book1.xlsx").Worksheets("Sheet1").Range("A1")
は
o_RngA1Cell
と短く書くことができます。
まずは「それだけでも便利で見やすくなる・他人も読みやすくなるな」「そういうメリットがあるな」と覚えて頂ければOKです。
なお、
Application.Workbooks("Book1.xlsx").Worksheets("Sheet1").Range("A1")
といった感じのオブジェクト式の書き方は
よく書籍やWeb記事で
Range("A1")
などと、階層構造のいっさいがっさいを省略して書かれます。
(たとえば、「Book1.xlsx」の「Sheet1」がアクティブになっている場合。)
なので、その
Range("A1")
を使って、
Dim o_RngA1Cell As Range
Set o_RngA1Cell = Range("A1")
と書くこともできます。
この場合、「なんだ、かえって長くなって不便じゃない?意味ある?」と思うかもしれませんが、
そもそも「Range("A1")」という書き方は、
1つのExcelファイルを扱っているときだけ、かつ、
今アクティブなブックの
今アクティブなシート
を扱っている時だけしか有効ではない=使えません。
例えば、
2つ以上のブックを同時に開いて操作する場合や
アクティブになっていないシートを操作したいとき
などはエラーになったり、
動きがおかしくなったりして、役に立たない、のです。
(もちろん、「Range("A1")」と書いたほうがいい場合も多少はありますが)
結局
Application.Workbooks("Book1.xlsx").Worksheets("Sheet1").Range("A1")
とか
Workbooks("Book1.xlsx").Worksheets("Sheet1").Range("A1")
といった、かたちで書く、
「階層構造を省略しない書き方」が一番エラーが少なめになるので
そう書くわけなんですが、
でもやっぱりこれだと、
延々とこれがプログラムのなかにたくさん表れてしまうとすっごく見づらい・読みにくい、ので
「o_RngA1Cell 」という短い単語に置き換えて読めるほうが、すっきり・読みやすく・見やすくなるのでそうします。
結局「Range("A1")」という短い「階層構造を省略しまくった書き方」は、サンプル用の書き方で、実務では「もっともエラーや誤作動が出やすい書き方・一番エラーが出やすい。」です。
実際、実務にはあまり使いません。
そのことは私たち初心者に対しては、最初にちゃんと説明しされないことがほとんどですので、どうぞ、お気をつけください。
『 実務では「Range("A1")」はあまり使わないでね。エラーや誤作動を起こしやすいから。ここではゴチャゴチャしてしまうと説明しづらくなるからしょうがなく階層構造を省略してるけど 』と説明してもらえることは非常に少ないです。
「階層構造」の「か」の字も言われないことが「本当に」「多い」です。
本当に、十分にお気を付けください。
もう少し実務的なかたちでご説明しますと、実際には
「セルをオブジェクト変数に代入する」という処理は逆にのちのち面倒になるのでやらず、
「シートをオブジェクト変数に代入する」という処理のほうが多いです。
その場合は例えば「o_Ws01」みたいなオブジェクト変数を作っておいて
Set o_Ws01 = Application.Workbooks("Book1.xlsx").Worksheets("Sheet1")
とか
Set o_Ws01 = Workbooks("Book1.xlsx").Worksheets("Sheet1")
といった感じで、シートをオブジェクト変数に代入します。
そうするとそのあとに「A1」セルを指定したいときは
o_Ws01.Range("A1")
と書くことができます。
これでも十分見やすいですし、もし「B1」セルを扱いたくなったら
o_Ws01.Range("B1")
と書くだけで済みます。
なので、このような「シートをオブジェクト変数に代入する」という形で書くことが多いです。(もちろん「絶対」ではないのでケースバイケースで書き分けます。)
それから、「With」のことを知っている人は「A1」セルを表現するのに
With Application.Workbooks("Book1.xlsx").Worksheets("Sheet1")
.Range("A1").Value = 222
End With
といった感じで書けることをご存知だと思います。
(上記の例ではA1セルに222という数値を書き込んでいます)
もちろんこれでもいいわけなんですが、この書き方も、複数出てくるとうっとおしい・読みにくくなってきます。
もちろん、1度や2度くらいこう書く程度ならいいですが(また、動作速度のことをあまり考えなくてもよいならいいですが)、そうじゃない、
・少し複雑な動きをさせたいような場合や、
・複数の別々の似たオブジェクトでWithを使うような場合、
で、かつ、出現頻度が多い場合、などは、
どれがどのシートか、どれがどのブックか?などが一目で判別がつきにくくなるので、ケースバイケースで、オブジェクト変数に代入してしまうほうがのちのちのメンテもラクちんな場合もあります。
オブジェクト変数に代入してからでもWithは使えますからそうしてしまっていいですし。(例えば以下のように)
Dim o_Ws01 As Object
Set o_Ws01 = Application.Workbooks("Book1.xlsx").Worksheets("Sheet1")
With o_Ws01
.Range("A1").Value = 222
End With
処理速度については、なにがどうとかは僕にはわかりません(というか大きな差はさほど出ないことが多いと思うので調べるのが面倒くさいです)が、遅いと感じてから色々としらべて、オブジェクト変数への代入をしたほうがいいのかダメなのかを考えればいいと思います。
最終的にどちらを使うべきかは、処理速度や組織内のルール・Excelの習熟度、メンテ、色々と考えて、その都度、変えていけばいいと思います。
※「好み」の問題もあると思います。
僕はバカで、かつ、Withを使ったコード自体が見づらくてあまり好きではないので、多少遅くなってもSetのほうだけ(オブジェクト変数だけ)を使ってしまうのですが、Withに慣れている人や本当に理屈を分かっていて処理速度その他の面からの理由でWithをよく使う人はWithにしろ!と言うと思います。
そこをどうするかは、やっぱり、処理速度や組織内のルール・Excelの習熟度、メンテ、色々と考えて、その都度、変えていけばいいと思います。
※参考記事
Access2000VBA・Excel2000VBA独学~ExcelVBAの高速化・速度アップ・スピードアップの方法について~