VBAでデザインパターンの「イテレータ(Iterator)パターン」をガチガチに実装しようとすると手間がかかりますが、VBA.Collection オブジェクトを活用することで、シンプルな記述で For Each による反復走査を行える仕組みを作ることができます。
ここでは、データを保持する要素クラスと、それを集約管理するコレクションクラスを用いた「イテレータもどき」の実装例を紹介します。
1. クラス設計の概要
- CIterator.cls: 1件分のデータを保持する要素クラス(名前と年齢を保持)
- CAggregate.cls: 内部に
VBA.Collectionを保持し、データの追加と反復用コレクションの提供を行う集約クラス - MainForTest.bas: 動作確認用の標準モジュール
2. クラスの実装
CIterator.cls(要素クラス)
実態は反復走査対象となるデータ(1レコード)を保持するシンプルなクラスです。
Option Explicit
Public Name As String
Public Age As Integer
CAggregate.cls(集約管理クラス)
内部で VBA.Collection をインスタンス化して管理します。iterator プロパティから内部コレクションを返すことで、呼び出し元が For Each で走査できるようにしています。
Option Explicit
Private m_collection As VBA.Collection
Private Sub Class_Initialize()
Set m_collection = New VBA.Collection
End Sub
Private Sub Class_Terminate()
Set m_collection = Nothing
End Sub
Public Sub Add(ByVal item As CIterator)
Call m_collection.Add(item)
End Sub
Public Property Get iterator() As Collection
Set iterator = m_collection
End Property
3. 利用例(標準モジュール)
MainForTest.bas
データを登録したあと、aggregate.iterator を通じて For Each で全要素を順番に取得して出力します。
Option Explicit
Sub IteratorTest()
Dim aggregate As CAggregate
Set aggregate = New CAggregate
Dim item As CIterator
' データの追加
Set item = New CIterator
item.Name = "太郎"
item.Age = 10
aggregate.Add item
Set item = New CIterator
item.Name = "花子"
item.Age = 12
aggregate.Add item
Set item = New CIterator
item.Name = "次郎"
item.Age = 30
aggregate.Add item
Set item = Nothing
' For Each による反復出力
Dim chkItem As CIterator
For Each chkItem In aggregate.iterator
Debug.Print chkItem.Name & " (" & chkItem.Age & "歳)"
Next chkItem
End Sub
ポイント
VBA標準の Collection をカプセル化しつつ、Property Get でコレクションを返す形にすることで、呼び出し側はコレクション内部の構造を意識せずに直感的な For Each 走査を行えます。
この記事の更新履歴
この記事は、生成AIを活用した自動レビュー・更新フローにより内容を見直し、必要な修正を反映しています。
2026年9月11日
- 変更blockquoteタグで崩れていたクラス・モジュールコードを整形済みのコードブロックに変更しました。
- 追加各クラス(CAggregate、CIterator)の役割とVBA.Collectionによる反復処理の仕組みについての解説を追加しました。
- 削除リンク切れとなっていた外部ブログの添付ファイルダウンロードリンクを削除しました。
