20240427 エクセルVBAクラス備忘録 コレクションひな形
<前書き>
エクセルVBAオブジェクト指向、初心者です。
VBA自体は、以前から使用していました。
オブジェクト指向というものがあることは、知っていましたが、ネットなどを見てもよく分からず、挫折した過去あり。
<以上前書き>
(素人なので間違っているかもしれません。汗。)
今回、collectionのひな形をいくつか書いておきます。
ここに書いたのは、簡単なもので、実際はもっとややこしくしないと実装できないと思います。
(これらでも手こずりましたが。汗)
(実践的なのは、次回以降にメモ程度に書こうかな。)
(注:最初の方のサンプルはクラスではありません。最後にクラスを使ったサンプルを書きました。)
////////////////////////////////////////
Sub コレクションひな形1()
Dim 果物 As New Collection
果物.Add "りんご"
果物.Add "みかん"
果物.Add "桃"
果物.Add "メロン"
Stop
End Sub
////////////////////////////////////////
Sub コレクションひな形1_2()
Dim 果物 As New Collection
果物.Add Item:="りんご"
果物.Add Item:="みかん"
果物.Add Item:="桃"
果物.Add Item:="メロン"
Stop
End Sub
////////////////////////////////////////
-----------------------------------------------
上記2つは同じ意味です。アイテムだけ、コレクションに入れている。
個々のアイテムの取り出し方は、
Debug.Print 果物(1)
Debug.Print 果物.Item(1)
でもいいです。
-----------------------------------------------
////////////////////////////////////////
Sub コレクションひな形2()
Dim ヒト型 As New Collection
ヒト型.Add "山田"
ヒト型.Add "太郎"
ヒト型.Add "男"
ヒト型.Add "30"
Stop
End Sub
////////////////////////////////////////
Sub コレクションひな形2_2()
Dim ヒト型 As New Collection
ヒト型.Add Item:="山田", Key:="姓" 'keyは一意であること
ヒト型.Add Item:="太郎", Key:="名"
ヒト型.Add Item:="男", Key:="性別"
ヒト型.Add Item:="30", Key:="年齢"
Debug.Print ヒト型(2) 'インデックスを使う
Debug.Print ヒト型("名") 'keyを使う
Dim hito As Variant
For Each hito In ヒト型
Debug.Print hito 'コレクションヒト型を回す
Next hito
Stop
End Sub
////////////////////////////////////////
--------------------------------------------------
上記も、果物とほぼ同じサンプルです。
keyを使ってます。keyは一意であることが条件です。
keyを使えば、
Debug.Print ヒト型("名")
で、取り出しが可能です。
全アイテムを取り出したければ、
For Each hito In ヒト型
で、可能です。
ちなみに、一部、keyを使わなかった場合、どうなるのかやってみましたが、特に問題ないです。
------------------------------------------------
//////////////////////////////////////////////
Sub コレクションひな形2_2_参考() '////////////一部にkeyなくても問題ないか(問題ない)
Dim ヒト型 As New Collection
ヒト型.Add Item:="山田", Key:="姓"
ヒト型.Add Item:="太郎" 'keyなし////////問題ない
ヒト型.Add Item:="男", Key:="性別"
ヒト型.Add Item:="30", Key:="年齢"
Debug.Print ヒト型(2) 'インデックスを使う
' Debug.Print ヒト型("名") 'keyを使う 'keyなし////////コメントアウトすれば問題ない
Dim hito As Variant
For Each hito In ヒト型
Debug.Print hito 'コレクションヒト型を回す
Next hito
Stop
End Sub
//////////////////////////////////////////////
--------------------------------------------
で、ここまで来て思うのは、「山田太郎さん 男 30歳」1人を集めたってしょうがないんだよ。
「山田太郎さん 男 30歳」なら1データでいいじゃん。
「佐藤花子さん 女 31歳」とか、複数人のデータの集まりがほしいんだよ・・・、となると思います。
で、このコレクションの上位のコレクション「ヒトビト型」を考える必要が出てきます。
また、変な(間違った)考え方ですが、
最初のひな形「果物」の場合、
果物.Add "りんご"
果物.Add "みかん"
果物.Add "桃"
果物.Add "メロン"
keyを加えても、
果物.Add "りんご","赤"
果物.Add "みかん","オレンジ"
果物.Add "桃","ピンク"
果物.Add "メロン","緑"
これじゃ、「数量」とか、「産地」とか何もいれられないじゃないか??となってしまいます。
ここでは書きませんが、果物の場合は、リンゴなどの各アイテムの下位のコレクションを考えたりする必要があると思います。
(上記の例の"赤"等の色は、keyではなく、下位のコレクションに書くべきでしょうね??。汗)
-----------------------------------------------
//////////////////////////////////////////////
Sub コレクションひな形3_2()
Dim ヒトビト型 As New Collection
Dim ヒト型 As Collection
Set ヒト型 = New Collection
ヒト型.Add Item:="山田", Key:="姓" 'keyは一意であること
ヒト型.Add Item:="太郎", Key:="名"
ヒト型.Add Item:="男", Key:="性別"
ヒト型.Add Item:="30", Key:="年齢"
ヒトビト型.Add Item:=ヒト型
Set ヒト型 = New Collection
ヒト型.Add Item:="佐藤", Key:="姓" 'keyは一意であること
ヒト型.Add Item:="花子", Key:="名"
ヒト型.Add Item:="女", Key:="性別"
ヒト型.Add Item:="31", Key:="年齢"
ヒトビト型.Add Item:=ヒト型
Debug.Print ヒトビト型(2).Item(1)
Debug.Print ヒトビト型(2).Item("年齢") 'ヒトビト型のItem = ヒト型(コレクション)
End Sub
/////////////////////////////////////////////////
-----------------------------------------------
上記のコードで、「ヒト型」2人分を、「ヒトビト型」に入れました。
下記のコードでは、「ヒトビト型」のkeyに「ヒト型」の姓を入れました。
(この方が少し実用的かと。)
-----------------------------------------------
/////////////////////////////////////////////////
Sub コレクションひな形3_2_参考() 'ヒトビト型にkeyを持たせる
Dim ヒトビト型 As New Collection
Dim ヒト型 As Collection
Set ヒト型 = New Collection
ヒト型.Add Item:="山田", Key:="姓" 'keyは一意であること
ヒト型.Add Item:="太郎", Key:="名"
ヒト型.Add Item:="男", Key:="性別"
ヒト型.Add Item:="30", Key:="年齢"
' ヒトビト型.Add Item:=ヒト型, Key:="山田" 'これOK
ヒトビト型.Add Item:=ヒト型, Key:=ヒト型("姓") 'これもOK
Set ヒト型 = New Collection
ヒト型.Add Item:="佐藤", Key:="姓" 'keyは一意であること
ヒト型.Add Item:="花子", Key:="名"
ヒト型.Add Item:="女", Key:="性別"
ヒト型.Add Item:="31", Key:="年齢"
' ヒトビト型.Add Item:=ヒト型, Key:="佐藤" 'これOK
ヒトビト型.Add Item:=ヒト型, Key:=ヒト型("姓") 'これもOK
Debug.Print ヒトビト型(1).Item(1)
Debug.Print ヒトビト型("山田").Item("名")
Debug.Print ヒトビト型("山田").Item("年齢")
Debug.Print ヒトビト型(2).Item(1)
Debug.Print ヒトビト型(2).Item("年齢") 'ヒトビト型のItem = ヒト型(コレクション)
Debug.Print ヒトビト型("佐藤").Item("年齢")
End Sub
//////////////////////////////////////////////
で、ここまで来ると、「「ヒト型」は「コレクション」より、「クラス」にした方がいいのでは?」という気になります。
'クラス「ヒト型」
Option Explicit
'宣言
Private m姓 As String
'宣言
Private m名 As String
'宣言
Private m性別 As String
'宣言
Private m年齢 As Long
'let
Public Property Let 姓(p姓 As String)
m姓 = p姓
End Property
'get
Public Property Get 姓() As String
姓 = m姓
End Property
'let
Public Property Let 名(p名 As String)
m名 = p名
End Property
'get
Public Property Get 名() As String
名 = m名
End Property
'let
Public Property Let 性別(p性別 As String)
m性別 = p性別
End Property
'get
Public Property Get 性別() As String
性別 = m性別
End Property
'let
Public Property Let 年齢(p年齢 As Long)
m年齢 = p年齢
End Property
'get
Public Property Get 年齢() As Long
年齢 = m年齢
End Property
//////////////////////////////////////////////
Function TEST_ヒト型1_3()
Dim ヒトビト型 As New Collection 'このコレクションはクラスではない
Dim vヒト型 As ヒト型
Set vヒト型 = New ヒト型
vヒト型.姓 = "山田"
vヒト型.名 = "太郎"
vヒト型.性別 = "男"
vヒト型.年齢 = "30"
ヒトビト型.Add vヒト型 'keyは付けていない
Set vヒト型 = New ヒト型
vヒト型.姓 = "佐藤"
vヒト型.名 = "花子"
vヒト型.性別 = "女"
vヒト型.年齢 = "31"
ヒトビト型.Add vヒト型 'newしないとコレクション上書きされてしまう
'コレクションの全部取り出し分からない
'ボツ
' Debug.Print ヒトビト型(1).item1.姓
' Debug.Print ヒトビト型(1).item1(1)
' Debug.Print ヒトビト型(1).Item(1)
' Debug.Print ヒトビト型(1).Item(1).姓
' Debug.Print ヒトビト型.Item(1).Item(1).姓
Debug.Print ヒトビト型.Item(1).姓 '正解
For Each vヒト型 In ヒトビト型
Debug.Print "vヒト型_data"
Debug.Print vヒト型.姓
Debug.Print vヒト型.年齢
Next vヒト型
Stop
End Function
/////////////////////////////////////
-----------------------------------
上記では、「ヒト型」をクラス、「ヒトビト型」をコレクションにしました。
For Each文で、コレクション「ヒトビト型」を回せば、各「ヒト型」のデータを確認できます。
-----------------------------------
最後に、「ヒトビト型」もクラスにします。
初心者なので、「いつも隣にIT」様(感謝いたします)
のHPを参考に、順番に「クラスに寄せて」いきます。
3段階あります。
-----------------------------------
/////////////////////////////////第一段階
クラス「ヒト型」は変更なし
////////////////////////////////
'クラス「ヒトビト型」
Option Explicit
Public Items As Collection
////////////////////////////////
Function TEST_ヒト型3_1()
'クラスにした
Dim vヒトビト型 As New ヒトビト型
Set vヒトビト型 = New ヒトビト型
Set vヒトビト型.Items = New Collection
Dim vヒト型 As ヒト型
Set vヒト型 = New ヒト型
vヒト型.姓 = "山田"
vヒト型.名 = "太郎"
vヒト型.性別 = "男"
vヒト型.年齢 = "30"
vヒトビト型.Items.Add vヒト型 'keyは付けていない
Set vヒト型 = New ヒト型
vヒト型.姓 = "佐藤"
vヒト型.名 = "花子"
vヒト型.性別 = "女"
vヒト型.年齢 = "31"
vヒトビト型.Items.Add vヒト型 'newしないとコレクション上書きされてしまう
For Each vヒト型 In vヒトビト型.Items 'コレクションであるItemsを回す
Debug.Print "vヒト型_data" '動く
Debug.Print vヒト型.姓
Debug.Print vヒト型.年齢
Next vヒト型
Stop
End Function
////////////////////////////////////
////////////////////////////////////第二段階
クラス「ヒト型」は変更なし
////////////////////////////////
'クラス「ヒトビト型」
Option Explicit
Public Items As Collection
Private Sub Class_Initialize()
Set Items = New Collection
End Sub
////////////////////////////////
Function TEST_ヒト型3_2() 'class_initialize
'クラスにした
Dim vヒトビト型 As New ヒトビト型
Set vヒトビト型 = New ヒトビト型
' Set vヒトビト型.Items = New Collection '不要
Dim vヒト型 As ヒト型
Set vヒト型 = New ヒト型
vヒト型.姓 = "山田"
vヒト型.名 = "太郎"
vヒト型.性別 = "男"
vヒト型.年齢 = "30"
vヒトビト型.Items.Add vヒト型 'keyは付けていない
Set vヒト型 = New ヒト型
vヒト型.姓 = "佐藤"
vヒト型.名 = "花子"
vヒト型.性別 = "女"
vヒト型.年齢 = "31"
vヒトビト型.Items.Add vヒト型 'newしないとコレクション上書きされてしまう
For Each vヒト型 In vヒトビト型.Items 'コレクションであるItemsを回す
Debug.Print "vヒト型_data" '動く
Debug.Print vヒト型.姓
Debug.Print vヒト型.年齢
Next vヒト型
Stop
End Function
//////////////////////////////
////////////////////////////////////第三段階
クラス「ヒト型」は変更なし
////////////////////////////////
'クラス「ヒトビト型」
Option Explicit
Public Items As Collection
Private Sub Class_Initialize()
Set Items = New Collection
Dim vヒト型 As ヒト型
Set vヒト型 = New ヒト型
vヒト型.姓 = "山田"
vヒト型.名 = "太郎"
vヒト型.性別 = "男"
vヒト型.年齢 = "30"
Items.Add vヒト型 'keyは付けていない
Set vヒト型 = New ヒト型
vヒト型.姓 = "佐藤"
vヒト型.名 = "花子"
vヒト型.性別 = "女"
vヒト型.年齢 = "31"
Items.Add vヒト型 'newしないとコレクション上書きされてしまう
For Each vヒト型 In Items 'コレクションであるItemsを回す
Debug.Print "vヒト型_data" '動く
Debug.Print vヒト型.姓
Debug.Print vヒト型.年齢
Next vヒト型
End Sub
////////////////////////////////////
Function TEST_ヒト型3_3() 'class_initializeの2
'クラスにした
Dim vヒトビト型 As New ヒトビト型
Set vヒトビト型 = New ヒトビト型
Stop
End Function
//////////////////////////////////
---------------------------------
上記の感じです。
あ~、ヒト型の個別具体データまで、ヒトビト型に入れたのは、入れすぎかも。
でも、一旦これで終了します。
データの取り出し方や入れ方ですが、for each文が便利ですが、クラスについては、すこし気になります。(クラスのプロパティの指定方法を変数で回したいが無理?)
'foreach文の使いどころ・・・(使えるところ、使えないところ) 考え中
①コレクションのitemsに入れる
②コレクションのitemを回す(取り出し)
③クラスのプロパティに入れる(上位コレクションを回して個々に入れる。個々にプロパティを設定しないとできない?まとめて入れられない?)
④クラスのプロパティを回す。上位コレクションを回して個々に取り出し。まとめて取り出すことはできない?(プロパティを変数にしたりとか考えたけどうまくできない)