みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。
「初心者でもわかるエクセルVBAのクラスモジュール」をテーマにシリーズ連載をしております。
前回の記事はこちら。
自作のコレクションから要素を取得するItemプロパティを作成しました。
さて、今回も自作のコレクションを便利にしていきますよ。
今回は、エクセルVBAで自作のコレクションに要素を追加するメソッドを作っていきます。
では、行ってみましょう!
前回のおさらい
まず、前回のおさらいからです。
以下のようなエクセル表があります。
この一行分のデータを表すPersonというクラスと、それを集合として取り扱うPersonsというクラスを作成しています。
Personクラスのコードはこちらです。
Private id_ As String
Public FirstName As String
Public Gender As String
Public Birthday As Date
Public Sub Greet()
MsgBox Me.FirstName & "です、こんにちは!"
End Sub
Public Sub Initialize(ByVal rng As Range)
id_ = rng(1).Value
FirstName = rng(2).Value
Gender = rng(3).Value
Birthday = rng(4).Value
End Sub
Public Property Get IsMale() As Boolean
IsMale = (Me.Gender = "male")
End Property
Public Property Get Id() As String
Id = id_
End Property
Public Property Let Id(ByVal newId As String)
If id_ <> "" Then
Debug.Print "Idは上書きすることはできません"
Else
id_ = newId
End If
End Property
Personのデータを格納するプロパティをはじめ、たくさんのメンバーを追加しました。
10~15行目の初期データをセットするInitializeメソッドについて、今回ちょっと変更を加えたりしますので、目を通しておいてくださいね。
Personsクラスのコードがこちらです。
Private items_ As Collection
Private Sub Class_Initialize()
Set items_ = New Collection
With Sheet1
Dim i As Long: i = 2
Do While .Cells(i, 1).Value <> ""
Dim p As Person: Set p = New Person
p.Initialize .Range(.Cells(i, 1), .Cells(i, 4))
items_.Add p, p.Id
i = i + 1
Loop
End With
End Sub
Public Property Get Item(ByVal key As Variant) As Person
Set Item = items_.Item(key)
End Property
前回はこのPersonsクラスに、要素を参照するためのItemプロパティを追加しました。
それを検証するための標準モジュールがこちら。
Sub MySub()
Dim myPersons As Persons: Set myPersons = New Persons
With myPersons
Debug.Print .Item(1).FirstName
.Item("a02").Greet
End With
End Sub
独自コレクションに要素を追加するメソッド
現状のPersonsクラスですが、Class_Initializeプロシージャにより、インスタンス生成時に前述のエクセル表のデータが追加されるようになっています。
しかし、新たに要素を追加したい場合はどうしたらよいでしょうか?
前回、Collection型のオブジェクト変数items_を隠蔽した今、標準モジュールから新しい要素を追加するのは不可能になってしまいました…
ということで、今回は独自コレクションのPersonsに、新たに要素を追加するAddメソッドを作成していきます。
シンプルにAddメソッドを作成する
クラスPersonsのAddメソッドのコード
シンプルに考えるなら、クラスPersonsに以下のようなコードを追加すれば良さそうです。
Public Function Add(ByVal values As Variant) As Person
Dim p As Person: Set p = New Person
p.Id = values(0)
p.FirstName = values(1)
p.Gender = values(2)
p.Birthday = values(3)
items_.Add p, p.Id
Set Add = p
End Function
エクセル表の1行分のデータに該当するデータを配列で渡してAddメソッドを呼び出すと、それを初期データとしたPersonオブジェクトを生成して、それをPersonsコレクションに追加するというものです。
Addメソッドの動作を確認する
標準モジュールに以下のようなコードを作成して、Stop時にローカルウィンドウを確認します。
Sub MySub()
Dim myPersons As Persons: Set myPersons = New Persons
Dim p As Person
Set p = myPersons.Add(Array("a04", "Jay", "male", #7/7/1995#))
Stop
End Sub
プライベート変数items_に新しい要素が追加されてますし、Addメソッドの戻り値として生成したPersonオブジェクトが取得できています。
処理の共通化
ただ、先ほどのAddメソッドの初期データの追加の処理が、PersonクラスのInitializeメソッドとほんのり処理がかぶっているのが気になります。
PersonsクラスのAddメソッドから、PersonクラスのInitializeメソッドを呼び出すようにしたら、処理が共通化できて気持ちが良さそうです。
ただ、Initializeメソッドで受け取る引数はRangeオブジェクトで、Addメソッドで渡したいのは配列…
ちょっと工夫が必要ですね。
データのタイプにより分岐する
PersonクラスのInitializeメソッドで値をVariantで受け取って、そのデータのタイプを調べて分岐するという作戦はどうでしょうか。
TypeName関数を使えば、受け取った変数のデータタイプを調べることができます。
Rangeオブジェクトであれば「Range」、Array関数で生成した配列であれば「Variant()」が得られます。
その他のタイプの場合を知りたい場合はこちらへどうぞ。
さて、それをベースに、Initializeメソッドを以下のように変更することができます。
Public Sub Initialize(ByVal values As Variant)
Select Case TypeName(values)
Case "Range"
id_ = values(1).Value
FirstName = values(2).Value
Gender = values(3).Value
Birthday = values(4).Value
Case "Variant()"
id_ = values(0)
FirstName = values(1)
Gender = values(2)
Birthday = values(3)
End Select
End Sub
Personsクラスの各メンバーをシンプルにまとめる
すると、PersonsクラスのAddメソッドは以下のようにシンプルにまとめることができます。
Public Function Add(ByVal values As Variant) As Person
Dim p As Person: Set p = New Person
p.Initialize values
items_.Add p, p.Id
Set Add = p
End Function
ついでに、PersonsクラスのClass_InitializeプロシージャもAddメソッドを使うことで、シンプルにまとめられます。
Private Sub Class_Initialize()
Set items_ = New Collection
With Sheet1
Dim i As Long: i = 2
Do While .Cells(i, 1).Value <> ""
Me.Add .Range(.Cells(i, 1), .Cells(i, 4))
i = i + 1
Loop
End With
End Sub
前述の標準モジュールのMySubを実行して、同じ結果が得られることを確認してください。
まとめ
以上、エクセルVBAで自作のコレクションに要素を追加するメソッドを作成する方法をお伝えしました。
少し、難易度が上がってきた感じはありますが、いい練習になるのではないでしょうか。
ここまで来ると色々な選択肢があるので、ぜひ好みの組み方を見つけてみてください。
さて、次回はコレクションの要素の削除について見ていきたいと思います。
どうぞお楽しみに!
連載目次:初心者でもわかる!エクセルVBAでクラスを作ろう
名前は聞いたことあるけどよくわからない「クラスモジュール」。本シリーズでは、初心者でも少しずつ丁寧にその作り方と便利さについてお伝えしていきますよ!- 【初心者でもできる】エクセルVBAで最も簡単なクラスを作る方法
- エクセルVBAでクラスに最も簡単なプロパティを追加する方法
- エクセルVBAで自作クラスをインスタンス化する方法
- エクセルVBAでクラスに最も簡単なメソッドを追加する方法
- エクセルVBAで表の1行分のデータを表すクラスを作成する方法
- エクセルVBAでProperty Getプロシージャを使って簡単なプロパティを作成する方法
- エクセルVBAでプロパティを他のモジュールからアクセスできないようにする方法
- エクセルVBAでProperty Letプロシージャを使ってプロパティ設定をする方法
- エクセルVBAでPropety Getプロシージャを使ってプライベート変数にアクセスする方法
- エクセルVBAでクラスのインスタンス生成時に初期データを格納するメソッドを作る方法
- エクセルVBAでインスタンスの集合をコレクション化する方法
- エクセルVBAでコレクション化したインスタンスを取り出す方法
- エクセルVBAでクラスモジュールを使って独自のコレクションを作る方法
- エクセルVBAでインスタンス生成時に自動で処理を実行するイベントプロシージャClass_Initialize
- エクセルVBAで自作コレクションのインスタンス生成時に初期データも投入する方法
- エクセルVBAで自作コレクションの要素を取得するプロパティの作り方
- エクセルVBAで自作のコレクションに要素を追加するメソッドを作成する
- エクセルVBAで自作コレクションの要素を削除するメソッドの作り方
- エクセルVBAでエクセル表のデータを反映するメソッドとクラスを使うメリット