20240328 エクセルVBAクラス備忘録
<前書き>
エクセルVBAオブジェクト指向、初心者です。
VBA自体は、以前から使用していました。
オブジェクト指向というものがあることは、知っていましたが、ネットなどを見てもよく分からず、挫折した過去あり。
<以上前書き>
今回の疑問
コレクション(collectionオブジェクト)は加算できるのか?
素人ですみません。ディクショナリは、集計できます。
コレクションて、集計でなく、その内容を変えること(加算とか)はできるのか?
(まあ、できるよね)
ということを、オブジェクト指向のコーディングに近づけて考えてみました。
下記に4個のコードを書いています。同じ挙動ですが、オブジェクト指向の度合いが高くなっていきます。
参考HP:「いつも隣にITのお仕事」様(エクセルVBAでクラスモジュールを使っての独自のコレクションを作る方法他の記事)
(感謝いたします。)
(もし、掲載で不都合ありましたら、すぐに削除いたします。)
時間なかったので、部分部分、Bing様に聞いています。
(感謝いたします。)
(もし、掲載で不都合ありましたら、すぐに削除いたします。)
コード1
//////////////////////////////////////
' 野菜クラスモジュール(VegetableClass)
Option Explicit
Private m_Type As String
Private m_Quantity As Double
Private m_Amount As Double
Public Property Let vegeType(ByVal p_Type As String)
m_Type = p_Type
End Property
Public Property Get vegeType() As String
vegeType = m_Type
End Property
Public Property Let Quantity(ByVal p_Quantity As Double)
m_Quantity = p_Quantity
End Property
Public Property Get Quantity() As Double
Quantity = m_Quantity
End Property
Public Property Let Amount(ByVal p_Amount As Double)
m_Amount = p_Amount
End Property
Public Property Get Amount() As Double
Amount = m_Amount
End Property
/////////////////////////////////
' 親モジュール
Sub Main()
Dim veggieCollection As Collection
Set veggieCollection = New Collection
' 人参のインスタンスを作成してコレクションに追加
Dim carrot As New VegetableClass 'インスタンス1
carrot.vegeType = "人参"
carrot.Quantity = 100
carrot.Amount = 100
veggieCollection.Add carrot, carrot.vegeType
' 大根のインスタンスを作成してコレクションに追加
Dim radish As New VegetableClass 'インスタンス2
radish.vegeType = "大根"
radish.Quantity = 50
radish.Amount = 500
veggieCollection.Add radish, radish.vegeType
' 人参の本数を10加算
carrot.Quantity = carrot.Quantity + 10
' 人参の金額を50加算
carrot.Amount = carrot.Amount + 50
' 結果を表示
Debug.Print "人参の本数: " & carrot.Quantity
Debug.Print "人参の金額: " & carrot.Amount
Stop 'veggieCollectionでItem1、Item2が取れた。
End Sub
--------------------------------------------
コード2
//////////////////////////////////////
' 野菜クラスモジュール(VegetableClass)はコード1と変わらず。
/////////////////////////////////////
'野菜のコレクションを独自コレクションに設定(Vegetables)
Public Items As Collection
////////////////////////////////////
' 親モジュール
Sub Main()
Dim veggieCollection As Vegetables
Set veggieCollection = New Vegetables
Set veggieCollection.Items = New Collection 'Itemsをインスタンス化
' 人参のインスタンスを作成してコレクションに追加
Dim carrot As New VegetableClass 'インスタンス1
carrot.vegeType = "人参"
carrot.Quantity = 100
carrot.Amount = 100
veggieCollection.Items.Add carrot, carrot.vegeType 'Itemsはcollectionなのでadd使える
' 大根のインスタンスを作成してコレクションに追加
Dim radish As New VegetableClass 'インスタンス2
radish.vegeType = "大根"
radish.Quantity = 50
radish.Amount = 500
veggieCollection.Items.Add radish, radish.vegeType
' 人参の本数を10加算
carrot.Quantity = carrot.Quantity + 10
' 人参の金額を50加算
carrot.Amount = carrot.Amount + 50
' 結果を表示
Debug.Print "人参の本数: " & carrot.Quantity
Debug.Print "人参の金額: " & carrot.Amount
Stop 'veggieCollectionでItem1、Item2が取れた。しかし独自クラスではない。「いつも隣にIT」様の独自コレクションを読んで直す予定
End Sub
--------------------------------------------
コード3(コード2とコード3は微妙な差しかないです。)
//////////////////////////////////////
' 野菜クラスモジュール(VegetableClass)はコード1と変わらず。
/////////////////////////////////////
'野菜のコレクションを独自コレクションに設定(Vegetables)
Public Items As Collection
Private Sub Class_Initialize() ’独自クラスのinitializeで、Itemsをコレクションしてしまう。
Set Items = New Collection
End Sub
/////////////////////////////////////
' 親モジュール
Sub Main()
Dim veggieCollection As Vegetables
Set veggieCollection = New Vegetables
' Set veggieCollection.Items = New Collection 'Itemsをインスタンス化 class_initializeにする(ここコメントアウト)
' 人参のインスタンスを作成してコレクションに追加
Dim carrot As New VegetableClass 'インスタンス1
carrot.vegeType = "人参"
carrot.Quantity = 100
carrot.Amount = 100
veggieCollection.Items.Add carrot, carrot.vegeType 'Itemsはcollectionなのでadd使える
' 大根のインスタンスを作成してコレクションに追加
Dim radish As New VegetableClass 'インスタンス2
radish.vegeType = "大根"
radish.Quantity = 50
radish.Amount = 500
veggieCollection.Items.Add radish, radish.vegeType
' 人参の本数を10加算
carrot.Quantity = carrot.Quantity + 10
' 人参の金額を50加算
carrot.Amount = carrot.Amount + 50
' 結果を表示
Debug.Print "人参の本数: " & carrot.Quantity
Debug.Print "人参の金額: " & carrot.Amount
Stop 'veggieCollectionでItem1、Item2が取れた。
End Sub
----------------------------------------------------
コード4
//////////////////////////////////////
' 野菜クラスモジュール(VegetableClass)はコード1と変わらず。
//////////////////////////
'野菜のコレクションを独自コレクションに設定(Vegetables)
Public Items As Collection
Private Sub Class_Initialize()
'
Set Items = New Collection
' 人参のインスタンスを作成してコレクションに追加
Dim carrot As New VegetableClass 'インスタンス1
carrot.vegeType = "人参"
carrot.Quantity = 100
carrot.Amount = 100
Items.Add carrot, carrot.vegeType 'Itemsはcollectionなのでadd使える
' 大根のインスタンスを作成してコレクションに追加
Dim radish As New VegetableClass 'インスタンス2
radish.vegeType = "大根"
radish.Quantity = 50
radish.Amount = 500
Items.Add radish, radish.vegeType
' 人参の本数を10加算
carrot.Quantity = carrot.Quantity + 10
' 人参の金額を50加算
carrot.Amount = carrot.Amount + 50
' 結果を表示
Debug.Print "人参の本数: " & carrot.Quantity
Debug.Print "人参の金額: " & carrot.Amount
End Sub
/////////////////////////////////////////
' 親モジュール
Sub Main()
Dim veggieCollection As Vegetables
Set veggieCollection = New Vegetables
Stop 'veggieCollectionでItem1、Item2が取れた。
End Sub
=======================================
基本的に4つのコードとも同じ動き。
でも、親モジュールでのstopの時のインスタンスの数は4番目が一番少ない。
今の自分は、コード1が基本になってしまう。いきなりコード4を書こうとすると、クラスを分割しない書き方にしてしまうかも。
あと、クラスの基本的な使い方かもしれないが、
' 人参のインスタンスを作成してコレクションに追加
Dim carrot As New VegetableClass 'インスタンス1
carrot.vegeType = "人参"
carrot.Quantity = 100
carrot.Amount = 100
この書き方で、クラスが複数作成可能なのに納得できる。
上記の小さいクラスをまとめようとcollectionを使ったが、コレクションへのまとめ方もいろいろありうるのか。
データとクラス、コレクションやディクショナリは、相性がよい感じですね。
次回も似たようなことを練習するつもりです。