■クラスモジュールを活用している人は少数?クラスモジュールを活用している人、あるいは活用できている人というのは、VBA を扱う人のなかでもかなり少数なのではないでしょうか。ある程度のプログラムを組むことはできるけど、クラスモジュールってそもそも必要なの? という人も多いのではないかと思います。
そもそもクラスモジュールは、なければないで、絶対に困る場面というのは存在しません。あったら便利であることは確かですが、正直、知らなくてもそれなりにどうにかなってしまうものです。しかしそれではなぜ、VBA(VB)にはクラスモジュールというものが存在するのでしょう。まったく実用性が無いとすれば、実装されているはずがありません。何かしらの存在意義があり、それが確かに利便性を含んでいるからこそ、クラスモジュールは存在します。
今回からは、このクラスモジュールについて扱ってみたいと思います。先ほども述べたように、クラスモジュールは絶対に習得しなければならない類のものではありません。しかし、その実用性を把握し活用することができれば、必ず個々のレベルアップに繋がります。ちょっと曖昧なままという人も、この機会に是非習得していただければと思います。
■そもそもそれってなんなんでしょクラスモジュールはよく、オブジェクトの雛形などと表現されます。しかしこれは非常に曖昧でわかりにくい表現だと思います。ある程度、クラスモジュールの知識が蓄積されてくると、なるほど確かに、と思うのですが、クラスモジュールに関する知識があまりないうちは、雛形であるなどと言われてもまるでピンときません。誰もがそうとは限りませんが、少なくとも私はそうでした。
そしてクラスモジュールを扱う上で避けて通れないのが『 インスタンス 』などの聞きなれないフレーズ。これがまたクラスモジュールを難解でわかりにくいものへと変えてくれます。結局いまいち理解が深まらないうちに、まぁ別にあとで勉強すればいいやとなってしまいがちです。
先ほども書いたように、クラスモジュールはオブジェクトの雛形と考えることができます。しかしその意味を考える前に、もう少し浅いところから、ゆっくり紐解いていきたいと思っています。また、オブジェクトってそもそもなんじゃ? という人は、予習を兼ねて以前の記事を読んでおくことをオススメします。オブジェクトがいったい何を表すものなのか、それを事前に理解しておくことはクラスモジュールを理解するうえで必ずプラスになるからです。
ExcelVBA を触ったことがある人なら、ワークシートのセルを何かしらのコードで操作した経験が少なからずあると思います。VBA を使って特定のセルを選択状態にしたり、あるいはそのセルに値を入力したり、一度くらいは誰もがやったことありますよね。
例えばある特定のセルを選択状態にし、そのセルに値を入力するには、次のように記述しますね。
Range("A1").Select
Range("A1").Value = "ExcelGamer"
上記のようなコードを実行すると、ワークシートのセルの『 A1 』が選択され『 ExcelGamer 』という文字列が値として設定されます。非常に簡単ですね。それに、非常に便利です。
ワークシートのセルは『 Range オブジェクト 』でしたね。そして、この Range オブジェクトが持つメソッドのひとつが『 Select メソッド 』であり、また、Range オブジェクトの持つプロパティのひとつが『 Value プロパティ 』です。
以前の講座でも解説したように、メソッドとは、オブジェクトが持っている関数です。引数をとることができることから、メソッドそのものが一種のプロシージャであるということも合点がいきます。そしてプロパティとはオブジェクトが持つ変数です。値を保持し、必要なときに参照したり変更したりすることができます。
先ほどの Range オブジェクトを例に取れば、『 Select 』というメソッドには指定されたセル(またはセル範囲)を選択するという動作が定義されています。そう、『 動作が定義 』されているわけです。そして『 Value 』というプロパティには、セルに入力されている内容を保持するという役目があります。そうです、『 保持するという役目 』があるんですね。
さて、ここまでくると、なんとなくオブジェクトというものがどのようにして設計されているかわかってきますね。マイクロソフトの Excel 開発チームは、ワークシートのセルに Range という名前を与えひとつのオブジェクトとして定義しました。そして、Select などのメソッドを実装(動作を定義)させ、Value などのプロパティを持つ(値などを保持する役目を持つ)ように設計しました。Range オブジェクトがそのように設計されているおかげで、我々は Range という言葉から繋がる様々なステートメントを用いて、ありとあらゆるプログラムを書くことができるわけです。
ほら、だんだんわかってきませんか?
つまり、Range オブジェクトの全ては、必ず Range クラスに属しています。そして Range クラスには、そのクラスに属するオブジェクトがどのようなメソッドを持ち、どのようなプロパティを持っているのかが全て定義されているのです。
クラスモジュールを用いたプログラミングとは、まさしくこれを、自分の手でやってしまおうということなんですね。自らクラスを定義し、そのクラスがどのように振舞うのかを記述し、オブジェクトの設計図を描いていくのです。
注意しなければならないのは、クラスモジュールで記述するのは、あくまでも設計図だということです。しかし、そのように言われてもいまいちピンとこないでしょう。その話は、もう少し突っ込んで詳しく解説したいと思います。
補足コラム:Rangeプロパティ
先ほどから、しきりにRangeオブジェクトという言葉を使っていますが、よく勘違いしてしまうことが多いので、補足します。
例えば『Range("A1")』などの記述をした場合の、このRangeというのは、実際はなんでしょうか。Rangeオブジェクトそのものを表すと勘違いしてしまいがちですが、実際には、このRangeはオブジェクトそのものではなく、プロパティです。ワークシートのセルを表すほかの方法として『Cells』がありますね。このCellsもプロパティです。これらのプロパティはRangeオブジェクトよりも上に位置するオブジェクトであるワークシートが持っているプロパティなんですね。
私達が特定のセルを操作したいと考えたときには、通常、RangeやCellsを使いますよね。実はこれはRangeオブジェクトを直接操作しているのではなく、ワークシートオブジェクトのRangeプロパティやCellsプロパティを介して、Rangeオブジェクトにアクセスしている状態だったのです。
Rangeオブジェクトはちょっと特殊なオブジェクトで、参照方法も多彩なため、なかなか完全に理解するのは難しいと思います。Excelの性質上、Rangeオブジェクトはどうしても複雑で汎用的な設計になってしまっています。無理に理解しようとせず、頭の片隅にでも情報として置いておきましょう。
■設計図があってこそのインスタンスさて、クラスモジュールがいったい何者なのか、おおよそわかってきたでしょうか。要するにクラスモジュールとは設計図のようなものです。たとえば我々がロボットの開発者だとして、実務的にしろ娯楽的にしろ、何かしらのロボットを開発したいとします。いきなりロボットを作り始める開発者は恐らくいません。まずは、その設計図を書くはずです。クラスモジュールにプロシージャを記述するということは、この設計図を作ることと同じです。自分の実現したい動作や結果を得るために、必要となるプログラムをひとつひとつ記述していきます。
それはそのロボットの動作、つまりメソッドであったり、あるいはそのロボットが持つ特徴、つまりプロパティであったりします。ロボットの開発者である我々が、自由にそれらを定義することができるのですね。
そうして設計図が出来上がったとき、初めてロボットを製造することが可能になりますね。そしてここでいう製造されたロボットこそが、インスタンスと呼ばれるものです。プログラミングではこれを、インスタンスを得る、あるいはインスタンスを生成する、などと言います。
インスタンスとはいわばオブジェクトの本体です。クラスモジュールに記述された設計図をもとに製造されたロボットそのもの、それがインスタンスです。インスタンスが生成できれば、あとは普段我々が行っているように、適宜そのインスタンスを介したプログラムを記述していけばいいわけです。セルを操作したいとき
Range
や
Cells
を使うのと同じように、生成したインスタンスからメソッドを呼び出したりプロパティを参照したりすればいいのです。
一度ここまでをまとめてみましょう。
オブジェクトはメソッドやプロパティを持つ
クラスモジュールはオブジェクトの設計図である
クラスモジュールには独自のメソッドやプロパティを記述できる
クラスモジュールという設計図からインスタンスという実体を生成する
インスタンスを生成して初めてオブジェクトとして利用できる
先ほどクラスモジュールをロボットの設計図に、インスタンスをロボット本体に例えました。ロボット=オブジェクトであり、そのように順を追って考えていくと、冒頭に書いた「クラスモジュールとはオブジェクトの雛形である」という言葉の意味もなんとなくわかるのではないでしょうか。
さて、それではここで一度考えてみましょう。
クラスモジュールを使ったプログラミングを行う『利点』とはいったいなんなのでしょうか。
これには様々なことが言えますが、まず一番大きいのはコードが簡潔に仕上がるということでしょう。どれほど複雑なオブジェクトであっても、オブジェクト自体があらかじめプロパティとして値を保持する仕組みを持っていれば、その情報を保持するための変数を別途定義する必要はありません。オブジェクトのインスタンスをひとつ生成しておけば、それだけでもう他にこのオブジェクトのための変数は要らないのですね。
そしてこれはメソッドについても同様のことが言えます。何かしらの動作が必要なときには、その都度処理をいちいち記述する必要はありません。メソッドを呼び出すだけで、いつでもどこでも、簡単に処理を呼び出すことが可能になるのです。
デバッグの面でも、クラスモジュールは有利です。なにかバグが発生したとき、どのオブジェクトが原因となっているのかさえ突き止めることができれば、そのオブジェクトを定義しているクラスモジュールの中身を見てみればいいのです。
仕様を変更したくなった場合にも、やはり同じようなことが言えますね。元となるクラスモジュールにさえ変更を加えておけば、そのオブジェクトが関係する全ての処理が一度に修復できてしまいます。頻繁に、様々な場面で活躍するオブジェクトであればあるほど、修正が一箇所で済むということの利便性は非常に大きなものとなります。
また、クラスモジュールを用いることの利点としてよく挙がるのが高い移植性です。
さすがに、ワークシート上の処理を記述したクラスモジュールをユーザーフォーム上でそのまま使うといったことはできませんが、あくまでも同じプラットフォーム上で動作することを前提にすれば、クラスモジュールの移植性は非常に高いと言えます。
たとえばユーザーフォームの初期化処理をクラスモジュールに記述しておけば、次に同じようなプログラムを作成しようとしたとき、新たにコードを書き直す必要はありません。クラスモジュールごと移植してしまえば、それでことが済むからです。
個人が趣味で作成しているプログラムの場合はそれほど関係ありませんが、複数の人間で協力して作り上げるプロジェクトの場合には、やはりクラスモジュールを用いることによって大きなメリットを得られる場合があります。
たとえば、DirectX の処理を一手に担うクラスを設計してあれば、それを根幹として複数の行程を同時に進行することができるでしょう。また、同じクラスを媒体としているため、あとあとプロジェクトを統合していく際に、根本的な問題が発生してくる確立も低く抑えることができるはずです。
このように、クラスモジュールには様々な利点があります。そして、わかってしまえば、それほど難しいことをやっているというわけでもありません。冒頭にも書いたように、クラスモジュールは絶対に必要な概念というわけではありません。しかし習得できれば必ず役に立つことも確かです。
どうしても『 難しい 』とか『 とっつきにくい 』というイメージが付きまとうクラスモジュール。まずはその概要をざっくりとでも構いませんから理解しておきましょう。オブジェクトの概念をある程度理解できていれば、それほど難しくないと思います。必要に応じて過去の Chapter から復習しながら、ゆっくりじっくり、理解していってみてください。
■格言
クラスモジュールはオブジェクトの設計図
設計図から生み出される実体がインスタンス意外と、順を追って理解していけば難しくないのではないでしょうか。
- 関連記事
-