私はクラスモジュールで変数をPublicで宣言する事に否定的ですが、
それでもクラスを使用するのと使用しないのとでは作業効率が全く違うので,
クラスを使用する事を強くお勧めします。
オチ Excel、VBAで集計を行いたいのであればPowerQueryやSQLを使用しましょう。
・なぜクラスを使用するのがいいのか?クラスを使用するとなにが違うのか?
VBAで作業を行う主な目的は(複数のブックの)複数のシートの複数のテーブルを使用して集計を行う事だと思いますが、これがクラスを使用しない場合は
Dim wb1 As WorkBook,wb2 As WorkBook
Dim ws1 As WorkSheet,ws2 As WorkSheet
Dim tbl1 As ListObject,tbl2 As ListObject
さらには
Dim path1 As String,path2 As String
とそれぞれの「オブジェクト」別に変数を宣言すると思いますが、これがクラスモジュールだと
'クラスモジュールのオブジェクト名、名前はClassとします
Private pwb As WorkBook
Private pws As WorkSheet
Private ptbl As ListObject
とそれぞれ一つの変数を宣言すると、
Public Sub Initialize(Byval wsName As String,Optional Byval Path As String = "",Optional Byval tblName As String = "")
If Path <> "" Then
Set pwb = WorkBooks.Open(Path,ReadOnly:=True)
Else
Set pWb = ThisWorkBook
End If
Set pWs = pwb.Sheets(wsName)
Dim val As Variant
val = tblName
If tblName = "" Then
val = 1
End If
If pws.ListObjects.Count > 0 Then
Set ptbl = pws.Listobjects(val)
End If
End Sub
と書くことが出来できます。
あとはこのクラスをブックやシートごとに個別に宣言してそれぞれのシートを代入すればいいです。
クラスを使用しないと同じ種類(型)の変数が沢山宣言され、重複、冗長になるだけでなく、
コードが長くなって、しかも修正が大変な上に結局やっている事が
「クラスのメンバーと全く同じ」
という非常におかしいことになります。
しかも変数があまりにも大量なので、変数に誤った値を代入してしまいます。
クラスを使用しなくても、
結局使用するオブジェクトのそれぞれの変数を宣言しなければならない事は何も変わらないのです
クラスの中のPrivate変数を操作するには
Public Property Get ws()as WorkSheet
Set ws = pws
End Property
とクラスモジュールの中に書いて、標準モジュールで(これも仲介役のクラスでいいのですが)
'注)標準モジュール
Dim clsObj As Class
Set clsObj = New Class
clsObj.Initialize "シート名","ファイルパス"
clsObj.ws いつもの操作
と、それぞれのプロパティー名を書くだけでシートやテーブルに対する操作が行えます
注意 Let Set と Get は「必ず両方用意しなければならないという事はありません」
Let Set だけでも
Get だけでも
いいです
Getの()As 型 と返すオブジェクト、値の型が不一致だと恐らくエラーになります
記述していない Let Set Get のPropertyの操作を行おうとすると当然エラーになります
クラスにオブジェクトや値を読み書きするだけなら非常に簡単です(これはいつものオブジェクトや変数に対する読み書きと同じです)
しかし、クラスで処理を行おうとすると難易度が跳ね上がります
なので、ますばクラスモジュールにVBAで必ず使用するオブジェクト、値を分類別に代入する事から始めてください
同じクラスオブジェクトを複数、一つの変数で作成することが出来ます(値を持つ)
例えば
collection.Add clsObj
dic.Add "キー",clsObj
と書けばコレクションならFor Each
dicならdic("キー")
それぞれ、別々の「独立した」クラスオブジェクトを操作することが出来ます
これによって、ブック、シート、テーブルの取り違えが無くなります
・クラスを使用するとサブプロシージャやFunctionの引数が激減する
クラスを使用しない場合は、すべての変数を引数として指定する必要がありますが、クラスオブジェクトであれば、変数のセットなので引数の数が激減します
・標準モジュールしか使用していない時は、処理ごとの標準モジュールに大量の引数で変数を引き渡す必要がありますが、クラスだと「Private変数」なのでこれが激減します、これが「カプセル化」です
・そもそもPrivate変数(カプセル化している)なので、クラス内のオブジェクト、変数に対する操作は、クラスモジュールないでSubで記述することが出来、Private変数なので、引数にする必要がありません
クラスモジュールを使用しない場合は呼び出し先のサブプロシージャに引数で変数を渡して値を汚さない事、Functionであれば、呼び出し元の変数に値を返すことに細心の注意を払う必要がありますが、クラスモジュールはPrivate変数なのでそれらを一切きにする必要がなくなります
もう我慢する必要はありません(値の読み書きに徹せず、複雑な処理を書いた場合は別ですが、、、)
最後に銀行口座を例にしたいと思います
自分のお給料や送金がまったくの他人の口座に振り込まれたらとても困りますよね?
お金の計算や処理が間違っていたら困りますよね?
なぜそういうことが起きないかというと、
それぞれの口座が独立して呼び出され
銀行口座クラスにはそれぞれ、口座番号、名義、残高といったプロパティが存在し(インターフェース)
送金などの処理を行うときはそれらのプロパティが1対1で行われるから(インターフェース)
他人の口座との取り違えが起きないのです
これがもし
口座番号1、口座番号2
名義1、名義2
口座残高1、口座残高2
という様に、大量の変数が存在していれば間違いなく取り違えが起きます
さらには自行内の取引だけでなく、他行への送金、預入、引き出しさらには保険、証券、国債、投資信託、借入、定期預金、当座預金口座、など、お金にまつわる全ての取引、決済の機能、システムとの通信が行われるのです
(同じお金だからと、お金にまつわるすべての事が全部ごっちゃになっているから銀行のシステムは巨大で複雑なのではないでしょうか?)