エクセルVBAで自作コレクションの要素を取得するプロパティの作り方


collection

photo credit: Hugo-90 Harold’s toy collection via photopin (license)

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

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

前回の記事はこちら。

エクセルVBAで自作コレクションのインスタンス生成時に初期データも投入する方法
「初心者でもわかるエクセルVBAのクラスモジュール」についてのシリーズです。今回は、エクセルVBAで自作コレクションのインスタンス生成時のイベントClass_Initializeで初期データも投入する方法です。

自作コレクションのクラスPersonsをイベントプロシージャClass_Initializeで初期化する方法をお伝えしました。

さて、この自作コレクションですが、現状だと要素の取得がちょっと回りくどいんです。

ということで、今回はエクセルVBAで自作コレクションの要素を取得するプロパティの作り方です。

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

スポンサーリンク

前回のおさらい

では、前回のおさらいから…!

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

エクセルVBAでクラス化するエクセル表

こちらのエクセル表をクラスで取り扱いをしていくというのが目標です。

まず、一行分のデータを扱うために、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クラスから生成したインスタンスを複数取り扱うコレクションのクラスPersonsがこちら。

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

これで、エクセル表のデータ全体を扱うことができるわけです。

前回、上記のコードのよいうに、クラスPersonsのインスタンス生成時にエクセル表のデータを自動で取り込むように作ったんです。

その確認用の標準モジュールがこちら。

Sub MySub()

Dim myPersons As Persons: Set myPersons = New Persons

Stop

End Sub

…超シンプルになりましたね。

独自コレクションにメンバーItemを追加する

さて、実際のPersonオブジェクトたちは、PersonsクラスのCollection型のパブリック変数Itemsに格納されています。

ですから、特定のPersonsオブジェクトを参照しようと思ったら

myPersons.Items.Item(1)
myPersons.Items.Item('a01')

などとする必要があります。

ちょっと回りくどいですし、普段使っているコレクションっぽくないですよね…

例えば、Personsクラス自体に、独自のメンバーとして「Item」を追加したらどうでしょう?

myPersons.Item(1)
myPersons.Item('a01')

と、こんな感じで参照ができて、普段使っているコレクションっぽいですよね。

コレクションの要素を取得するItemプロパティ

では、実際に実装していきましょう。

クラスPersonsにItemプロパティを追加します。

値を返すプロパティでいいので、Property Getプロシージャですね。

そして、引数として整数のインデックスまたは、文字列型のキーかどちらかを受け取る必要があるので、Variant型で引数を受けるようにしましょう。

Public Property Get Item(ByVal key As Variant) As Person
    Set Item = Items.Item(key)
End Property

それで、その引数を使って、パブリック変数Itemsが参照するコレクションからItemメソッドを使って要素を取り出して挙げるということです。

自作のItemプロパティで要素を取得する

では、作成した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

インデックス1の要素のFirstNameを表示、キー「a02」の要素のGreetメソッドを実施ですね。

実行すると以下のように正しく参照できていることを確認できます。

自作コレクションのItemプロパティのテスト

Itemsプロパティを隠蔽する

さて、PersonsコレクションにItemプロパティを追加しました。

そうなると、ここでふとした疑問が…

パブリック変数Itemsですが、これ他のモジュールからアクセスできる必要…あります?

今回追加したItemプロパティや、要素の追加をするAddメソッドなどを用意すれば、Itemsがパブリックである必要はなさそうです。

Itemsプロパティを隠蔽しちゃいましょうか。

パブリック変数をプライベート変数に変更する

まず、Personsクラスのパブリック変数Itemsをプライベート変数に変更します。

プライベート変数なので、頭文字も小文字にしてアンダースコアを付与しました。

Private items_ As Collection

それに合わせて、Personsクラスのコードを置換しましょう。

Ctrl + F で以下の置換ダイアログが表示しますので、検索文字列を「Items」、置換後文字列を「items_」にします。

あと、「大文字と小文字を区別する」にもチェック入れておきましょう。

変数名を置換する

結果的に、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

これで、他のモジュールからアクセスができなくなります。

ただ、Class_Initializeでの初期データ投入と、Itemプロパティによる参照はできるはずです。

前述の標準モジュールのコードを実行して確認しておきましょうね。

まとめ

以上、エクセルVBAで自作コレクションの要素を取得するプロパティの作り方をお伝えしました。

これで、コレクションっぽく要素を参照できるようになりましたね。

次回は、Personsクラスに要素を追加するAddメソッドを作成していきます。

エクセルVBAで自作のコレクションに要素を追加するメソッドを作成する
「初心者でもわかるエクセルVBAのクラスモジュール」をテーマにシリーズ連載をしております。今回は、エクセルVBAで自作のコレクションに要素を追加するAddメソッドを作成する方法について見ていきます。

どうぞお楽しみに!

連載目次:初心者でもわかる!エクセル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をコピーしました