Mutable_Yunの業務改善ブログ

業務改善や生産性向上のブログです。自動化の手段として、VBAやRPAの勉強に役立つ解説をしています。

VBAのクラスを使う① クラスを使うためのオブジェクトとメソッドの前提知識

VBAはクラスをきちんと理解しなくても、かなりの自動化ができます。そのため、初心者にやさしい一方で、クラスの必要性を感じないため、きちんと分かっていない人も多いのではないでしょうか。

私は長い間VBAのクラスモジュールを使わずに自動化ツールを作成してきました。

しかし、Pythonという別のプログラミング言語を学ぶ過程で不可欠でクラスをきちんと勉強し直しました。

そしてVBAに戻ってきたとき、甘やかされていた事、そしてちゃんと勉強しなかったのはもったいなかったと気づきました。

メソッドという言葉も勘違いしていました。クラスが使えるようになり一皮むけた感がありました。
そのため、ここに私が勉強したクラスとその周辺のことをまとめたいと思います。

この記事は初段です。
レベルについてはExcel VBAの実力(レベル)を定義してみる 初心者~三段をご参照ください。

目次

クラスとオブジェクト

まず、すでに知っている言葉を復習します。

オブジェクト:そこに実態のあるモノ。(例えば、Rangeオブジェクト)
確認のために、オブジェクトブラウザーを開きます。

表示⇒オブジェクトブラウザー

f:id:mutable_yun:20190910205253p:plain
オブジェクトブラウザー

Rangeを検索してクリックすると、右に'Rangeのメンバー'が表示されます。
f:id:mutable_yun:20190910210054p:plain

右に出てくるメンバーからおなじみのCellsをクリックすると下のキャプチャの説明が表示されます。

f:id:mutable_yun:20190910210451p:plain
Rangeオブジェクトのメンバー、Cellsはプロパティ

ついでに、もう一個くらい調べてみたいのでよく使う(?)ClearContentsをクリック。

f:id:mutable_yun:20190910211718p:plain
ClearContentsはFunctionプロシジャだった!

つまり、クラスとはプロパティやFunctionプロシジャやSubプロシジャを持つ!
むむむ、オブジェクトについて調べていたはずなのにいつの間にかクラスの話になっています。

二度見してもクラスって書いてある。。。Rangeってオブジェクトだったはずなのに。。。

おそらくここが一番肝でクラスとオブジェクトがこんがらがってしまう原因です。

これは、エクセルでは最初から操作できるオブジェクトはクラス名と名前が同じだからです!

つまり、Rangeクラスとは、
「Rangeオブジェクトというのがありますよ。そして、そのRangeオブジェクトはCellsプロパティやClearContentsというFunctionプロシジャーという関数を持っていますよ」

と言う説明書です。
クラスは説明書なので実態はありません。しかしRangeクラスとRangeオブジェクトと名前が同じなので混乱してしまったのです。

メソッドとは

オブジェクトの説明書であるクラスの中にSubプロシジャやFunctionプロシジャが記述されていることがわかりました。
この、Functionプロシジャ(独自の関数)やSubプロシジャのことをメソッドと呼びます。

ここで私は今までの勘違いに気づきました。

勘違い:メソッドとはClearContentsのようにオブジェクトを操作するモノ
正解:メソッドとはオブジェクト自身が持つプロシジャ
(例、Rangeは自分自身のValueプロパティを初期化するClearContentsというメソッドを持っている)

そこで、前述の「つまり、クラスとはプロパティやFunctionプロシジャやSubプロシジャを持つ!」を
より厳密に言うと、
「クラスはどのようなプロパティやメソッドを持つかを説明するオブジェクトの説明書で、そのオブジェクトのプロパティを変更したりメソッドを実行したりしている!」のが普段、私たちがやっていることです。

そして、自分独自のクラス(自分が作りたいオブジェクトがどんなプロパティとメソッド(FunctionやSubプロシジャ)を持つのか=どんな役割をさせたいのか)を定義するのがクラスモジュールです。

そして標準モジュールで「さっき書いたクラスの説明書」のオブジェクトを作ります。

標準モジュールでオブジェクトを作ると、ようやくRange(Cells(1 , 1), Cells(1, 1)).ClearContentsのように

自分で作ったオブジェクト名.メソッド名(:プロシジャとして作る)

の形で使えるようになります。

Rangeはもとから使えるようにしてあるオブジェクトと言う事です。


ちなみに下記のコードを実行すると、A1セルにこんにちはと表示されます。

Cells(1 , 1) = "こんにちは"

ということはこれはCellsオブジェクトでしょうか。

f:id:mutable_yun:20190910214125p:plain
Cellsで検索

Cellsクラスは見当たりません。こちらはWorkSheetクラスの、(WorkSheetクラスで定義されたWorkSheetオブジェクトの)Cellsプロパティです。つまりActiveSheet.Cells(1, 1) = "こんにちは"の略です。

このあたりも理解を難しくしていると思います。


クラスモジュールはコードの書き方の解説は多いですが、オブジェクトそのものの説明があまり多くないように感じたので、参考になればと思います。

クラスのコードの書き方はネットでとても分かりやすい解説が多いので、コードの書き方はそちらに譲ろうか迷いましたが、実用的なモノが作りたいので、次回はできるだけ簡単に作りたいと思います。

<余談>
この記事を書くにあたりRangeクラスのメンバーをあらためていろいろ見ていると、びっくりするぐらいたくさんのプロパティやメソッドがありました。Rangeに大量に書き込むと遅くなるのはこのためです。なので、配列内で計算して最後にペタッと貼り付けるとものすごく早くなります。

そして見つけてしまった。Speakメソッド。こんなの知らない。。。

Sub SpeakはRangeオブジェクトのメソッド()
    ActiveSheet.Cells(1, 1).Value = "こんにちは"
    Range("A1").Speak
End Sub

なんと!
しかも「こんにちは」の代わりに英語にしたり、さらにその英語の綴りを間違えてみると・・・!?

試してみて下さい。