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番目が一番少ない。