エクセルVBA オブジェクト指向備忘録クラス ディクショナリとクラス(とコレクション)

20240331 エクセルVBAクラス備忘録 

エクセルVBA オブジェクト指向備忘録クラス ディクショナリとクラス(とコレクション)

 

<前書き>
エクセルVBAオブジェクト指向、初心者です。
VBA自体は、以前から使用していました。
オブジェクト指向というものがあることは、知っていましたが、ネットなどを見てもよく分からず、挫折した過去あり。
<以上前書き>

 

今回の疑問
前回、クラス・コレクションを使ったコードを4つ書きました。
今回、クラスとディクショナリで考えてみます。(注)

YouTubeに「こいこいの人工知能」様の「ディクショナリ」を使った動画があり、参考にさせてもらいました。
その動画は、ユーザー定義型(type)とディクショナリを扱うものですが、typeをクラスに置き換えました。

で、できたものを、前回同様に、「いつも隣にITのお仕事」様
(エクセルVBAでクラスモジュールを使っての独自のコレクションを作る方法他の記事)に合わせて、
コードを4個作成しています。

(ご両者には大変感謝しております。)
(もし、掲載で不都合ありましたら、すぐに削除いたします。)

 

注:実際の内容は、ディクショナリを使ってできた「売上」を「売上コレクション」として一つにまとめるものです。
もしかしたら、ディクショナリにしながら、コレクションに突っ込むことができるのかもしれませんが、初心者なのですみません。

オブジェクト指向のコーディングに近づけて考えてみました。

下記に4個のコードを書いています。同じ挙動ですが、オブジェクト指向の度合いが高くなっていきます。
参考HP:「いつも隣にITのお仕事」様(エクセルVBAでクラスモジュールを使っての独自のコレクションを作る方法他の記事)
(感謝いたします。)
(もし、掲載で不都合ありましたら、すぐに削除いたします。)

時間なかったので、部分部分、Bing様に聞いています。
(感謝いたします。)
(もし、掲載で不都合ありましたら、すぐに削除いたします。)

 

コード1
//////////////////////////////////////
' 売上クラスモジュール
    Public mise As String
    Public d As String  '割引あった日の文字列
    Public beer As Long    '合計金額用
    Public eda As Long
/////////////////////////////////

' 親モジュール
Sub Rensou2class_collection()  'まだ
    Dim dic As Object, i As Long, data, keys
    Dim n As Long, m As Long
    Dim v売上() As 売上      '配列
    
    Dim v売上コレクション As Collection
    Set v売上コレクション = New Collection
    
    Set dic = CreateObject("Scripting.Dictionary")

    'ビールデータ格納
    data = Sheets("sheet1").Range("A1").CurrentRegion
    
    For i = 2 To UBound(data)
        If Not dic.Exists(data(i, 2)) Then  '存在するか確認(店)
            dic.Add data(i, 2), n      'n最初は0(例:B店,0)
            
            ReDim Preserve v売上(n)
            Set v売上(n) = New 売上   'new
            v売上(n).mise = data(i, 2)
            v売上(n).beer = data(i, 3)
            v売上(n).eda = data(i, 4)
            
            '割引  ’〇の時に日付
            If data(i, 5) <> "" Then
                v売上(n).d = data(i, 1)
            End If
            
            n = n + 1
        Else      '存在する場合
            '保存場所の値を格納
            m = dic(data(i, 2))    '店の位置がmに取れる
            
            v売上(m).beer = v売上(m).beer + data(i, 3)
            v売上(m).eda = v売上(m).eda + data(i, 4)
            
            '割引
            If data(i, 5) <> "" Then
                If v売上(m).d = "" Then
                    v売上(m).d = data(i, 1)
                Else
                    v売上(m).d = v売上(m).d & vbCrLf & data(i, 1)
                End If
            End If
        End If
    Next i

    For i = LBound(v売上) To UBound(v売上)
        v売上コレクション.Add v売上(i), v売上(i).mise
   
    Next i

  Stop
End Sub

--------------------------------------------
コード2
//////////////////////////////////////
' 売上クラスはコード1と変わらず。

/////////////////////////////////////
'売上のコレクションを独自コレクションに設定(売上コレクション)
Public Items As Collection

////////////////////////////////////
' 親モジュール
Sub Rensou2class_collection()  'OK

 

    Dim dic As Object, i As Long, data, keys
    Dim n As Long, m As Long
    Dim v売上() As 売上      '配列
    
    
    Dim v売上コレクション As 売上コレクション
    Set v売上コレクション = New 売上コレクション
    Set v売上コレクション.Items = New Collection
    
 
    
    Set dic = CreateObject("Scripting.Dictionary")

    'ビールデータ格納
    data = Sheets("sheet1").Range("A1").CurrentRegion
    
    For i = 2 To UBound(data)
        If Not dic.Exists(data(i, 2)) Then  '存在するか確認(店)
            dic.Add data(i, 2), n      'n最初は0(例:B店,0)
            
            ReDim Preserve v売上(n)
            Set v売上(n) = New 売上   'new
            v売上(n).mise = data(i, 2)
            v売上(n).beer = data(i, 3)
            v売上(n).eda = data(i, 4)
            
            '割引  ’〇の時に日付
            If data(i, 5) <> "" Then
                v売上(n).d = data(i, 1)
            End If
            
            n = n + 1
        Else      '存在する場合
            '保存場所の値を格納
            m = dic(data(i, 2))    '店の位置がmに取れる
            
            v売上(m).beer = v売上(m).beer + data(i, 3)
            v売上(m).eda = v売上(m).eda + data(i, 4)
            
            '割引
            If data(i, 5) <> "" Then
                If v売上(m).d = "" Then
                    v売上(m).d = data(i, 1)
                Else
                    v売上(m).d = v売上(m).d & vbCrLf & data(i, 1)
                End If
            End If
        End If
        
        
    Next i

    For i = LBound(v売上) To UBound(v売上)
        v売上コレクション.Items.Add v売上(i), v売上(i).mise
    Next i


    Stop
End Sub

--------------------------------------------
コード3(コード2とコード3は微妙な差しかないです。)
//////////////////////////////////////
' 売上クラスはコード1と変わらず。

/////////////////////////////////////
'売上のコレクションを独自コレクションに設定(売上コレクション)
Public Items As Collection

Private Sub Class_Initialize()
    Set Items = New Collection
End Sub


/////////////////////////////////////
' 親モジュール
Sub Rensou2class_collection()  'OK


    

    Dim dic As Object, i As Long, data, keys
    Dim n As Long, m As Long
    Dim v売上() As 売上      '配列
    
    
    Dim v売上コレクション As 売上コレクション
    Set v売上コレクション = New 売上コレクション
'    Set v売上コレクション.Items = New Collection    'ここコメントアウト!!!
    
 
    Set dic = CreateObject("Scripting.Dictionary")

    'ビールデータ格納
    data = Sheets("sheet1").Range("A1").CurrentRegion
    
    For i = 2 To UBound(data)
        If Not dic.Exists(data(i, 2)) Then  '存在するか確認(店)
            dic.Add data(i, 2), n      'n最初は0(例:B店,0)
            
            ReDim Preserve v売上(n)
            Set v売上(n) = New 売上   'new
            v売上(n).mise = data(i, 2)
            v売上(n).beer = data(i, 3)
            v売上(n).eda = data(i, 4)
            
            '割引  ’〇の時に日付
            If data(i, 5) <> "" Then
                v売上(n).d = data(i, 1)
            End If
            
            n = n + 1
        Else      '存在する場合
            '保存場所の値を格納
            m = dic(data(i, 2))    '店の位置がmに取れる
            
            v売上(m).beer = v売上(m).beer + data(i, 3)
            v売上(m).eda = v売上(m).eda + data(i, 4)
            
            '割引
            If data(i, 5) <> "" Then
                If v売上(m).d = "" Then
                    v売上(m).d = data(i, 1)
                Else
                    v売上(m).d = v売上(m).d & vbCrLf & data(i, 1)
                End If
            End If
        End If
        
    Next i

    For i = LBound(v売上) To UBound(v売上)
        v売上コレクション.Items.Add v売上(i), v売上(i).mise
    
    Next i

    Stop
End Sub

----------------------------------------------------
コード4
//////////////////////////////////////
' 売上クラスはコード1と変わらず。

/////////////////////////////////////
'売上のコレクションを独自コレクションに設定(売上コレクション)
Public Items As Collection


Private Sub Class_Initialize()

    Dim dic As Object, i As Long, data, keys
    Dim n As Long, m As Long
    Dim v売上() As 売上      '配列
       

    Set Items = New Collection
    
    
    Set dic = CreateObject("Scripting.Dictionary")

    'ビールデータ格納
    data = Sheets("sheet1").Range("A1").CurrentRegion
    
    For i = 2 To UBound(data)
        If Not dic.Exists(data(i, 2)) Then  '存在するか確認(店)
            dic.Add data(i, 2), n      'n最初は0(例:B点,0)
            
            ReDim Preserve v売上(n)
            Set v売上(n) = New 売上   'new
            v売上(n).mise = data(i, 2)
            v売上(n).beer = data(i, 3)
            v売上(n).eda = data(i, 4)
            
            '割引  ’〇の時に日付
            If data(i, 5) <> "" Then
                v売上(n).d = data(i, 1)
            End If
            
            n = n + 1
        Else      '存在する場合
            '保存場所の値を格納
            m = dic(data(i, 2))    '店の位置がmに取れる
            
            v売上(m).beer = v売上(m).beer + data(i, 3)
            v売上(m).eda = v売上(m).eda + data(i, 4)
            
            '割引
            If data(i, 5) <> "" Then
                If v売上(m).d = "" Then
                    v売上(m).d = data(i, 1)
                Else
                    v売上(m).d = v売上(m).d & vbCrLf & data(i, 1)
                End If
            End If
        End If
        
    Next i

    For i = LBound(v売上) To UBound(v売上)
        Items.Add v売上(i), v売上(i).mise
    
    Next i

 

End Sub

/////////////////////////////////////////
' 親モジュール
Sub Rensou2class_collection()  'OK

    Dim v売上コレクション As 売上コレクション
    Set v売上コレクション = New 売上コレクション
    

    Stop
End Sub


=======================================
基本的に4つのコードとも同じ動き。
でも、親モジュールでのstopの時のインスタンスの数は3番目が一番少ない。