1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VBAのクラスについての一番わかりやすい説明

Last updated at Posted at 2025-09-17
私はクラスモジュールで変数を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

という様に、大量の変数が存在していれば間違いなく取り違えが起きます

さらには自行内の取引だけでなく、他行への送金、預入、引き出しさらには保険、証券、国債、投資信託、借入、定期預金、当座預金口座、など、お金にまつわる全ての取引、決済の機能、システムとの通信が行われるのです
(同じお金だからと、お金にまつわるすべての事が全部ごっちゃになっているから銀行のシステムは巨大で複雑なのではないでしょうか?)

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?