エクセルVBAで自作のコレクションに要素を追加するメソッドを作成する


add

みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。

「初心者でもわかるエクセルVBAのクラスモジュール」をテーマにシリーズ連載をしております。

前回の記事はこちら。

エクセルVBAで自作コレクションの要素を取得するプロパティの作り方
「初心者でもわかるエクセルVBAのクラスモジュール」というテーマでシリーズ連載をしております。今回は、エクセルVBAで自作コレクションの要素を取得するItemプロパティの作り方をお伝えします。

自作のコレクションから要素を取得するItemプロパティを作成しました。

さて、今回も自作のコレクションを便利にしていきますよ。

今回は、エクセルVBAで自作のコレクションに要素を追加するメソッドを作っていきます。

では、行ってみましょう!

前回のおさらい

まず、前回のおさらいからです。

以下のようなエクセル表があります。

エクセル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オブジェクトが取得できています。

PersonsコレクションのAddメソッドの検証

処理の共通化

ただ、先ほどのAddメソッドの初期データの追加の処理が、PersonクラスのInitializeメソッドとほんのり処理がかぶっているのが気になります。

PersonsクラスのAddメソッドから、PersonクラスのInitializeメソッドを呼び出すようにしたら、処理が共通化できて気持ちが良さそうです。

ただ、Initializeメソッドで受け取る引数はRangeオブジェクトで、Addメソッドで渡したいのは配列…

ちょっと工夫が必要ですね。

データのタイプにより分岐する

PersonクラスのInitializeメソッドで値をVariantで受け取って、そのデータのタイプを調べて分岐するという作戦はどうでしょうか。

TypeName関数を使えば、受け取った変数のデータタイプを調べることができます。

TypeName(変数名)

Rangeオブジェクトであれば「Range」、Array関数で生成した配列であれば「Variant()」が得られます。

その他のタイプの場合を知りたい場合はこちらへどうぞ。

TypeName 関数 (Visual Basic for Applications)

さて、それをベースに、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で自作コレクションの要素を削除するRemoveメソッドの作り方についてお伝えしていきます。

どうぞお楽しみに!

連載目次:初心者でもわかる!エクセルVBAでクラスを作ろう

名前は聞いたことあるけどよくわからない「クラスモジュール」。本シリーズでは、初心者でも少しずつ丁寧にその作り方と便利さについてお伝えしていきますよ!
  1. 【初心者でもできる】エクセルVBAで最も簡単なクラスを作る方法
  2. エクセルVBAでクラスに最も簡単なプロパティを追加する方法
  3. エクセルVBAで自作クラスをインスタンス化する方法
  4. エクセルVBAでクラスに最も簡単なメソッドを追加する方法
  5. エクセルVBAで表の1行分のデータを表すクラスを作成する方法
  6. エクセルVBAでProperty Getプロシージャを使って簡単なプロパティを作成する方法
  7. エクセルVBAでプロパティを他のモジュールからアクセスできないようにする方法
  8. エクセルVBAでProperty Letプロシージャを使ってプロパティ設定をする方法
  9. エクセルVBAでPropety Getプロシージャを使ってプライベート変数にアクセスする方法
  10. エクセルVBAでクラスのインスタンス生成時に初期データを格納するメソッドを作る方法
  11. エクセルVBAでインスタンスの集合をコレクション化する方法
  12. エクセルVBAでコレクション化したインスタンスを取り出す方法
  13. エクセルVBAでクラスモジュールを使って独自のコレクションを作る方法
  14. エクセルVBAでインスタンス生成時に自動で処理を実行するイベントプロシージャClass_Initialize
  15. エクセルVBAで自作コレクションのインスタンス生成時に初期データも投入する方法
  16. エクセルVBAで自作コレクションの要素を取得するプロパティの作り方
  17. エクセルVBAで自作のコレクションに要素を追加するメソッドを作成する
  18. エクセルVBAで自作コレクションの要素を削除するメソッドの作り方
  19. エクセルVBAでエクセル表のデータを反映するメソッドとクラスを使うメリット

タイトルとURLをコピーしました