注)私は全くの素人です。
VBAのクラスについて一番多い説明と実例は
'Person
Option Explicit
' メンバ変数
Private pName As String
Private pAge As Long
Public Sub Initialize(Byval ws As Worksheet,Byval 行番号 As long)
pName = ws.cells(行番号,"~")
pAge = ws.cells(行番号,"~")
End Sub
だと思われます。
しかしこれではテーブルの、しかもたった1行(1件)の記録でしかない上に、わざわざクラスを作って その処理固有の 個別のプロパティーを登録するという、非常に面倒で手間がかかる上に、むしろ余計に複雑になったという事にしかなりません。
そこで貴方はこう思ったはずです。
ListObjectのListRow(.Range)となにが違うのですか?
と。
しかし、これが複数のユーザーフォームの画面と、そのやりとりと考えると確かに便利になります(私はやっていないですが)。
例えばID TextBox、名前 TextBox、年齢 TextBoxなどがあって、それを別の画面とのやり取りや、データを検索するユーザーフォームのその検索結果を表示するなどです(実際にVBAにもインターフェースはあります)(接続端子や共通規格のイメージでいいですUSBやHDMIの様な)。
VBAにもイベントがありますが、他の言語では当たり前の機能なのだと思います。
クラスを解説する記事で次に多い例はCarClassです。
PersonClassとCarClassと来ると次はそれらを合わせたオーナーリストでしょうか。販売履歴のクラスもあるとどの顧客がどの車種を何年保有しているか?という事も出来そうです。
この説明はExcelでの表計算や集計ではなく、本当の本当にアプリケーション開発の画面や機能やデータのやり取りの解説をしていたのです。
私たち一般ユーザーはPowerQueryやSQLの様な、コードが短くて、簡単で、高機能な集計機能を求めているのに。
そもそもこのよくあるクラスの説明というのはクラスの定義という、「クラスそのもの」について教科書的な説明を書いているだけです。
なので、私たちがVBAで行う処理においてのクラスの活用方法というのは、VBAで必ず行う(書く)と言っても過言ではない、すでにExcelやVBAにあるオブジェクトのやその機能と処理を、扱いやすく組み替えた(書き換えた)上でクラスに書くことによって高い汎用性を持たせ、どのVBAのコードでも使える、流用できるようにすることです。
例えばVBAで処理を行うなら
pWb As WorkBook
pWs As WorkSheet
pTbl As ListObject
pData As Variant
pRowCount
pColumnCount
あたりは鉄板ですし、ブックを開くのであれば、そのブックがちゃんと存在するのかをチェックする処理を書いておいた方がより堅実なプログラムになるでしょう。
クラスを作る上で忘れないでおいてほしいのは
Set rng = Range("A1")
text = Range("A1").Value
Range("A1").Value = text
という様に、ただオブジェクトの代入や値の読み取り、書き込みを行うだけなら非常に簡単だという事です。これは普段からいつもやっている事です。
そう、実はWorkBookもWorkSheetもRangeもオブジェクトであり、全部クラスだったんですねー。
ここでクラスにオブジェクトや値の登録と値の読み書きだけでなく、処理も書くと一気に難易度が上がります。
あれ?この処理はどこのクラスにあったっけ?
となったり、クラスはそれぞれ独立しているので、他のクラスの処理(メソッド)を利用するためには、結局、他のクラスにクラスを直書きしなければならないとか、他のクラスの処理の引数にクラスを指定しなければならないとなって、むしろこんがらがってややこしくなります。
だからそれぞれのクラスには
テーブルとテーブルに関するデータを登録するクラス
それらのテーブルクラスを束ねるテーブルsクラス(コレクションやディクショナリーを利用して)
一つのテーブルに対しての処理をまとめたテーブル操作クラス(テーブルクラスの中で直接インスタンスして利用)
複数のテーブルに対して行う処理(検索や比較など)をまとめたクラス(テーブルsクラスに直接インスタンスして)
など、「役割を一つに絞ったクラスを作る」ことに徹した方がいいと思います(むしろそうでないと、書いた自分自身が複雑すぎて扱えません)
どうでしょうか?
'Person
Option Explicit
' メンバ変数
Private pName As String
Private pAge As Long
私はもっと早く知りたかったです(同じコードをあちこちに書かなくて済んだので)。