エクセルVBAでクラスモジュールを使って独自のコレクションを作る方法

collection

photo credit: www.ilkkajukarainen.fi IMG_0059 via photopin (license)

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

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

さて、前回の記事はこちら。

エクセルVBAでコレクション化したインスタンスを取り出す方法
「初心者でもわかるエクセルVBAのクラスモジュール」をテーマにシリーズでお送りしております。今回は、Itemメソッドを使ってエクセルVBAでコレクション化したインスタンスを取り出す方法についてお伝えします。

インスタンスのコレクションからその要素を取り出す方法をお伝えしました。

これで、だいぶ形になってきた感じはあるのですが、もうちょっと欲を出しちゃいましょうか。

それは、独自のコレクションを作るです。

これまでは、既存のCollectionオブジェクトを使ってきたのですが、独自のコレクションを作れたら、集合に対して便利なメソッドやプロパティを追加できますもんね。

ということで、エクセル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

エクセル表のフィールドをプロパティとして持つだけでなく、いくつかの便利なメンバーも独自で追加しています。

上記、クラスはエクセル表の1行分のデータを表すものなので、それをコレクションに格納して取り扱おうと、そしてその参照方法についていくつかテストしているのが、以下のModule1になります。

Sub MySub()

Dim myPersons As Collection: Set myPersons = 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))
        myPersons.Add p, p.Id
        i = i + 1
    Loop
End With

Debug.Print myPersons(2).FirstName 'インデックスでの参照を確認
Debug.Print myPersons("a03").Birthday 'キーでの参照を確認

'コレクションの要素についてループ
For Each p In myPersons
    Debug.Print p.Id, p.FirstName, p.Gender, p.Birthday
Next p

End Sub

今回やりたいこと:独自のコレクションを作る

標準モジュールModule1の処理を見ると、3~13行目はそもそもコレクションの準備として、

  • 新規コレクションを生成
  • データ行の分だけ繰り返し
    1. インスタンスを生成
    2. インスタンスのプロパティに初期データをセット

というような処理をしています。

ていうか、この部分って、どうせいつも必要な処理ですよね?

そしたら、これもクラスに寄せることはできまいか…!?

そう考えると、ふと思い浮かびます。

  • WorksheetオブジェクトにはWorksheetsコレクション
  • WorkbookオブジェクトにはWorkbooksコレクション
  • WindowオブジェクトにはWindowsコレクション

あらかじめ用意されているオブジェクトのいくつかには、その集合を扱うための専用のコレクションが用意されています。

てことは、PersonオブジェクトにはPersonsコレクションがあったらほうが便利じゃね?

それで、Personのコレクションにいつもやるようさ操作は、そっちに機能をもたせたほうがいいんじゃね?

ということになりそうです。トライしてみましょう。

独自のコレクションを作成する

さて、では手探りをしながら、独自コレクションPersonsを作成していきましょう。

新規クラスモジュールを挿入する

独自コレクションとはいいつつも、コレクションはオブジェクトなので、クラスモジュールの挿入からスタートです。

VBEメニューの「挿入」から「クラスモジュール」を選択して、新たなクラスモジュールを挿入します。

新規クラスモジュールを挿入する

そして、プロパティウィンドウの「(オブジェクト名)」を編集して、挿入したクラスモジュールの名前を「Persons」に変更します。

プロパティウィンドウでクラス名をPersonsに

クラスモジュールにCollection型のプロパティを追加する

それで、その新たに作ったまっさらのクラスモジュールPersonsに何を書いていくか…ということなのです。

まず、コレクションを持たせたいので、「データ」としてコレクションを定義しちゃいましょうか。

プロパティとして、Collection型のオブジェクト変数を定義するのです。

クラスモジュールPersonsの宣言セクションに…えい!

Public Items As Collection

これで、PersonsクラスにCollection型のオブジェクトを参照するItemsというプロパティを定義することになります。

Itemsプロパティは以下のようにすることで、Personsクラスのインスタンスが持つCollectionオブジェクトを返します。

Persons.Items

ですから、それに対してAddメソッドやItemメソッドなどが使えるという寸法です。

これで、クラスPersonsにはコレクションを持たせることができるはず…!

独自コレクションの確認するマクロ

いったんこの時点で確認してみましょう。

標準モジュールModule1を以下のように変更しました。

Sub MySub()

Dim myPersons As Persons: Set myPersons = New Persons
Set myPersons.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))
        myPersons.Items.Add p, p.Id
        i = i + 1
    Loop
End With

Stop

End Sub

1つ目のポイントは4行目ですが、ほらItemsプロパティはCollection型、つまりオブジェクトなので、宣言するだけでは実体化されていません。

なので、Setステートメントで、Newで生成したインスタンスを参照設定してあげる必要があります。

それで、11行目は各インスタンスについて、インスタンス内のCollectionオブジェクトにAddメソッドで追加しているというわけですね。

実行して、Stopの際のローカルウィンドウを確認します。

ローカルウィンドウでItemsプロパティの内容を確認

無事に、データが投入されているのが確認できますね。

まとめ

以上、エクセルVBAでクラスモジュールを使って独自のコレクションを作る方法をお伝えしました。

プロパティとしてCollection型のオブジェクト変数を持たせることで、ひとまず独自コレクションとしての機能は実現できます。

ただ、「myPersons.Items.~」っていちいち書かないといけないので、ちょっとかっこ悪いですね。独自のAddメソッドとか、Itemメソッドがあったら「myPersons.Add」「myPersons.Item」とできますね。

なんとなく、Itemsプロパティはプライベートにしたいですし…

ということで、まず次回は独自コレクションPersonsの初期データ投入について進めていきます。

エクセルVBAでインスタンス生成時に自動で処理を実行するイベントプロシージャClass_Initialize
「初心者でもわかるエクセルVBAのクラスモジュール」のシリーズです。今回はエクセルVBAでインスタンス生成時に自動で処理を実行するイベントプロシージャClass_Initializeの使い方です。

どうぞお楽しみに!

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