Excel VBA 連想配列(ハッシュ テーブル)

Excel VBA のトップに戻る
Excel VBA 目次

基本操作
日本語変数と、Excelの計算式を記述
OSのバージョンとExcelのバージョンを取得
IE のバージョンを取得
データを並び替え
大量データを照合
ソートして順位(ランク)を設定
二次元配列ソート(Access データベースをシーケンシャルに更新する)
連想配列を使って検索を高速化する
 ・Dictionary オブジェクトと Collection オブジェクト

索引


連想配列を使って検索を高速化する

 配列を使って、順次検索して照合する方法だと、データ件数が多くなると、相応して時間がかかります。
うまいやり方がないかと調べていて「連想配列(ハッシュ テーブル)」の存在を知りました。
 下記サイトで、VBA での「連想配列」の使い方が、分かりやすく書かれていました。

 VBAで連想配列 〜 Scripting.Dictionary
http://www.niji.or.jp/home/toru/notes/17.html

 上のサイトで教えていただいた方法を、下記のマクロに応用したら、処理速度が10倍以上、速くなりました。目からうろこ、大感激です。

 下の例は、商社が、ユーザから受けた「注文リスト(10,000件)」を、「仕入先」別に仕分けして、「品目コード」単位に数量まとめした「集計リスト」を作成する処理の例です。
 「注文リスト」は、「品目マスタ(15,000件)」と照合して、「単価」や「仕入先」を設定します。
 「注文リスト」と「品目マスタ」を、順次処理で照合すると、10,000件×15,000件/2=7千5百万回 の照合作業が発生します。これでは、いくらパソコンの速度が速くても、それなりの時間がかかってしまいます。
 「連想配列」を使って、「品目コード」に索引を付けると、直接アクセスできるので、飛躍的に速くなりました。

このマクロをダウンロードできます。DictionaryVBA01.xls

 Dictionaryオブジェクトの使い方については、下記も参考になります。
Excel(エクセル) VBA入門:Dictionaryオブジェクトを利用する
http://www.eurus.dti.ne.jp/yoneyama/Excel/vba/vba_dictionary.html
Excel VBA スキルアップコレクション 連想配列を作成する
http://www.seiji-tsubosaki.net/ExcelTech/ExcelVBASkillUpCollection/Contents_02.htm


Option Explicit
Option Base 1

   Dim 品目マスタ配列() As Variant
   Dim 品目マスタ件数 As Integer
   Dim 注文リスト配列() As Variant
   Dim 注文リスト件数 As Integer
   Dim 注文集計配列(10000, 8) As Variant
   Dim 集計品目件数 As Integer
   Dim 処理行 As Integer
   Dim 開始日時 As Variant
   Dim 終了日時 As Variant
   Dim エラー配列(5000, 2) As Variant
   Dim エラー件数 As Integer
   Dim 品目コード As String
      
Sub 発注仕分け連想配列版()

   Dim 品目マスタ索引 As Object        'Scripting.Dictionary オブジェクト
   Dim 品目マスタ配列添え字 As Integer 'Scripting.Dictionary オブジェクトのデータ

   Dim 注文集計索引 As Object          'Scripting.Dictionary オブジェクト
   Dim 注文集計配列添え字 As Integer   'Scripting.Dictionary オブジェクトのデータ
   
   開始日時 = Now                      '開始時刻を変数に格納します。

   Call 注文リスト読み込み
   Call 品目マスタ読み込み
   
   '★品目マスタ索引を作成★
   Set 品目マスタ索引 = CreateObject("Scripting.Dictionary")  '★連想配列の定義
   For 処理行 = 2 To 品目マスタ件数 + 1
      品目コード = 品目マスタ配列(処理行, 1)                  '品目コード
      品目マスタ索引(品目コード) = 処理行
   Next 処理行
   
   '集計作業
   Set 注文集計索引 = CreateObject("Scripting.Dictionary")    '★連想配列の定義
   
   集計品目件数 = 0
   エラー件数 = 0
   For 処理行 = 2 To 注文リスト件数 + 1
      品目コード = 注文リスト配列(処理行, 1)
      If 品目マスタ索引.Exists(品目コード) = True Then
         '★品目マスタに存在した場合
         品目マスタ配列添え字 = 品目マスタ索引(品目コード)
         
         If 集計品目件数 = 0 Then '一件目の注文品目
            集計品目件数 = 集計品目件数 + 1
            注文集計配列(集計品目件数, 1) = 品目マスタ配列(品目マスタ配列添え字, 2)    '仕入先
            注文集計配列(集計品目件数, 2) = 品目コード                             '品目コード
            注文集計配列(集計品目件数, 3) = 注文リスト配列(処理行, 2)                  '数量
            注文集計配列(集計品目件数, 4) _
            = 品目マスタ配列(品目マスタ配列添え字, 3) * 注文集計配列(集計品目件数, 3)  '金額
            注文集計配列(集計品目件数, 5) _
            = 品目マスタ配列(品目マスタ配列添え字, 4) * 注文集計配列(集計品目件数, 3)  '重量

            注文集計索引(品目コード) = 集計品目件数  '★既存品目として索引に追加

         Else                    '二件目以降の注目品目
            '既存チェック
            If 注文集計索引.Exists(品目コード) = True Then
               '既存の場合、数量のみ足し込む
               注文集計配列添え字 = 注文集計索引(品目コード)
               注文集計配列(注文集計配列添え字, 3) _
               = 注文集計配列(注文集計配列添え字, 3) + 注文リスト配列(処理行, 2)               '数量
               注文集計配列(注文集計配列添え字, 4) _
               = 品目マスタ配列(品目マスタ配列添え字, 3) * 注文集計配列(注文集計配列添え字, 3) '金額
               注文集計配列(注文集計配列添え字, 5) _
               = 品目マスタ配列(品目マスタ配列添え字, 4) * 注文集計配列(注文集計配列添え字, 3) '重量
            Else
               '新規の場合は、配列に追加する
               集計品目件数 = 集計品目件数 + 1
               注文集計配列(集計品目件数, 1) = 品目マスタ配列(品目マスタ配列添え字, 2)    '仕入先
               注文集計配列(集計品目件数, 2) = 品目コード                           '品目コード
               注文集計配列(集計品目件数, 3) = 注文リスト配列(処理行, 2)                  '数量
               注文集計配列(集計品目件数, 4) _
               = 品目マスタ配列(品目マスタ配列添え字, 3) * 注文集計配列(集計品目件数, 3)  '金額
               注文集計配列(集計品目件数, 5) _
               = 品目マスタ配列(品目マスタ配列添え字, 4) * 注文集計配列(集計品目件数, 3)  '重量

               注文集計索引(品目コード) = 集計品目件数  '★既存品目として索引に追加
            End If
         End If
      Else '品目マスタに存在しない
         エラー件数 = エラー件数 + 1
         エラー配列(エラー件数, 1) = 品目コード
         エラー配列(エラー件数, 2) = 注文リスト配列(処理行, 2)
      End If
   Next 処理行
   
   Call 結果出力
   Call エラー出力
   
   ThisWorkbook.Worksheets("スタート").Activate
   終了日時 = Now
   
   Range("F10").Value = "処理時間は、" _
   & Format(終了日時 - 開始日時, "hh時間nn分ss秒") & " でした。"
   
   Range("F11").Value = "マスタに存在しない品目は、" _
   & エラー件数 & " でした。"
   
   MsgBox "処理時間は、" _
   & Format(終了日時 - 開始日時, "hh時間nn分ss秒") & " でした。" & vbNewLine _
   & "マスタに存在しない品目は、" & エラー件数 & " でした。"

End Sub


Sub 発注仕分け順処理版()

   Dim マスタ検索行 As Integer
   Dim 集計検索行 As Integer
   Dim 既存フラグ As String
   Dim マスタ存在フラグ As String

   開始日時 = Now                ' 開始時刻を変数に格納します。

   Call 注文リスト読み込み
   Call 品目マスタ読み込み
   
   '集計作業
   集計品目件数 = 0
   エラー件数 = 0
   For 処理行 = 2 To 注文リスト件数 + 1
      既存フラグ = ""
      マスタ存在フラグ = ""
      品目コード = 注文リスト配列(処理行, 1)

      For マスタ検索行 = 2 To 品目マスタ件数 + 1
         If 品目コード = 品目マスタ配列(マスタ検索行, 1) Then
            マスタ存在フラグ = "存在"
            If 集計品目件数 = 0 Then '一件目の注文品目
               集計品目件数 = 集計品目件数 + 1
               注文集計配列(集計品目件数, 1) = 品目マスタ配列(マスタ検索行, 2)    '仕入先
               注文集計配列(集計品目件数, 2) = 品目コード                         '品目コード
               注文集計配列(集計品目件数, 3) = 注文リスト配列(処理行, 2)          '数量
               注文集計配列(集計品目件数, 4) _
               = 品目マスタ配列(マスタ検索行, 3) * 注文集計配列(集計品目件数, 3)  '金額
               注文集計配列(集計品目件数, 5) _
               = 品目マスタ配列(マスタ検索行, 4) * 注文集計配列(集計品目件数, 3)  '重量
   
            Else                    '二件目以降の注目品目
               '既存チェック
               For 集計検索行 = 1 To 集計品目件数
                  If 注文集計配列(集計検索行, 2) = 品目コード Then
                     '既存の場合、数量のみ足し込む
                     注文集計配列(集計検索行, 3) _
                     = 注文集計配列(集計検索行, 3) + 注文リスト配列(処理行, 2)       '数量
                     注文集計配列(集計検索行, 4) _
                     = 品目マスタ配列(マスタ検索行, 3) * 注文集計配列(集計検索行, 3) '金額
                     注文集計配列(集計検索行, 5) _
                     = 品目マスタ配列(マスタ検索行, 4) * 注文集計配列(集計検索行, 3) '重量
                     既存フラグ = "既存"
                     Exit For
                  End If
               Next 集計検索行
               
               If 既存フラグ = "" Then
                  '新規の場合は、配列に追加する
                  集計品目件数 = 集計品目件数 + 1
                  注文集計配列(集計品目件数, 1) = 品目マスタ配列(マスタ検索行, 2)    '仕入先
                  注文集計配列(集計品目件数, 2) = 品目コード                     '品目コード
                  注文集計配列(集計品目件数, 3) = 注文リスト配列(処理行, 2)          '数量
                  注文集計配列(集計品目件数, 4) _
                  = 品目マスタ配列(マスタ検索行, 3) * 注文集計配列(集計品目件数, 3)  '金額
                  注文集計配列(集計品目件数, 5) _
                  = 品目マスタ配列(マスタ検索行, 4) * 注文集計配列(集計品目件数, 3)  '重量
               End If
            End If
         End If
      Next マスタ検索行
      
      If マスタ存在フラグ = "" Then  '品目マスタに存在しない
         エラー件数 = エラー件数 + 1
         エラー配列(エラー件数, 1) = 品目コード
         エラー配列(エラー件数, 2) = 注文リスト配列(処理行, 2)
      End If
   Next 処理行
   
   Call 結果出力
   Call エラー出力
   
   ThisWorkbook.Worksheets("スタート").Activate
   終了日時 = Now
   
   Range("F15").Value = "処理時間は、" _
   & Format(終了日時 - 開始日時, "hh時間nn分ss秒") & " でした。"
   
   Range("F16").Value = "マスタに存在しない品目は、" _
   & エラー件数 & " でした。"
   
   MsgBox "処理時間は、" _
   & Format(終了日時 - 開始日時, "hh時間nn分ss秒") & " でした。" & vbNewLine _
   & "マスタに存在しない品目は、" & エラー件数 & " でした。"
   
End Sub


Private Sub 結果出力()
   Dim 追加シート名初期 As String
   Dim 追加シート名 As String
   Dim 重複 As Integer
   Dim シート As Worksheet
   Dim シート数 As Integer
   Dim 仕入先 As String
   Dim 仕入先前 As String
   Dim 数量合計 As Long
   Dim 金額合計 As Long
   Dim 重量合計 As Long

   追加シート名初期 = "注文集計結果"
   追加シート名 = 追加シート名初期

   For 重複 = 1 To 100
   ' 100枚まで追加しても重複しないように追番を設定します。
      For Each シート In Worksheets
         If シート.Name = 追加シート名 Then
            追加シート名 = 追加シート名初期 & "(" & 重複 & ")"
         End If
      Next シート
   Next 重複
   シート数 = Worksheets.Count
   Worksheets("テンプレート").Copy After:=Worksheets(シート数)
   ActiveSheet.Name = 追加シート名
   
   Range("A2").Resize(集計品目件数, 5).Value = 注文集計配列
    
   Range("A1").CurrentRegion.Sort _
      Key1:=Range("A1"), Order1:=xlAscending, _
      Key2:=Range("B1"), Order2:=xlAscending, _
      Header:=xlYes
      
   仕入先前 = Range("A2").Value
   
   For 処理行 = 2 To 集計品目件数 + 2
      仕入先 = Range("A1").Cells(処理行, 1).Value
      If 仕入先 = 仕入先前 Then
         数量合計 = 数量合計 + Range("C1").Cells(処理行, 1).Value
         金額合計 = 金額合計 + Range("D1").Cells(処理行, 1).Value
         重量合計 = 重量合計 + Range("E1").Cells(処理行, 1).Value
      Else
         仕入先前 = 仕入先
         Range("F1").Cells(処理行 - 1, 1).Value = 数量合計
         Range("G1").Cells(処理行 - 1, 1).Value = 金額合計
         Range("H1").Cells(処理行 - 1, 1).Value = 重量合計
         
         数量合計 = Range("C1").Cells(処理行, 1).Value
         金額合計 = Range("D1").Cells(処理行, 1).Value
         重量合計 = Range("E1").Cells(処理行, 1).Value
      End If
   Next 処理行
End Sub


Private Sub エラー出力()
   Dim 追加シート名初期 As String
   Dim 追加シート名 As String
   Dim 重複 As Integer
   Dim シート As Worksheet
   Dim シート数 As Integer

   追加シート名初期 = "エラー品目"
   追加シート名 = 追加シート名初期

   For 重複 = 1 To 100
   ' 100枚まで追加しても重複しないように追番を設定します。
      For Each シート In Worksheets
         If シート.Name = 追加シート名 Then
            追加シート名 = 追加シート名初期 & "(" & 重複 & ")"
         End If
      Next シート
   Next 重複
   シート数 = Worksheets.Count
   Worksheets("エラーテンプレ").Copy After:=Worksheets(シート数)
   ActiveSheet.Name = 追加シート名
   
   Range("A2").Resize(エラー件数, 2).Value = エラー配列

End Sub


Private Sub 注文リスト読み込み()

   ThisWorkbook.Worksheets("注文リスト").Activate
   注文リスト配列 = Range("A1").CurrentRegion
   注文リスト件数 = UBound(注文リスト配列) - 1 '一行目は項目名のため除外
   
End Sub


Private Sub 品目マスタ読み込み()

   ThisWorkbook.Worksheets("品目マスタ").Activate
   品目マスタ配列 = Range("A1").CurrentRegion
   品目マスタ件数 = UBound(品目マスタ配列) - 1 '一行目は項目名のため除外
   
End Sub

 解説

 Dictionary オブジェクト は、「データ キー」と、「組みとなる項目」を格納するオブジェクトです。
 構文
 Scripting.Dictionary

 Dictionary オブジェクトは、PERL の関連配列と同等です。
任意の型のデータにできる項目は、配列に格納されます。
項目は、重複しないキーで関連付けられます。
キーは各項目を取得するのに使用され、通常、整数型か文字列型ですが、配列にはできません。

Dictionary オブジェクトは厳密な意味では配列ではありませんが、複数の値を保管できるデータ構造という点で、配列と類似した機能を持っています。
Dictionary オブジェクトには、For Each…Next ステートメント、With…End With ステートメントなどのオブジェクト プログラミング コンストラクトを使用した作業が可能であることや、長さを調整する必要がない、という配列を使った作業にはない利点があります。

配列の代わりに Dictionary オブジェクトを使用してデータ セットを保管する場合、Dictionary オブジェクトの Exists メソッドを呼び出し、目的のアイテムに対するキーを渡すことにより、特定のアイテムがディクショナリに存在するかどうかをすばやく調べることができます。
ただし、Exists メソッドでは、ディクショナリ内のアイテムの位置または出現回数に関する情報は返されません。

配列に対して Filter 関数を使用する方法では別の配列が返されますが、Dictionary オブジェクトに対して Exists メソッドを使用すると、ブール型 (Boolean) の値が返されるという利点があります。検索アイテムの出現回数が重要ではない場合は、Dictionary オブジェクトを使用するとコードが簡潔になります。

 MSDN ライブラリの、「ファイル システムからファイルを返す」に記載されている GetFiles プロシージャと TestGetFiles プロシージャでも、Dictionary オブジェクトの使用について説明されています。

 Dictionary オブジェクトの詳細については、MSDN ライブラリの、http://technet.microsoft.com/ja-jp/scriptcenter/ff731125 を参照してください。

 下のコードは、Dictionary オブジェクトの作成方法の例です。

Dim d                   '変数を宣言します。
Set d = CreateObject(Scripting.Dictionary)
d.Add "a", "Athens"     'キーと項目を追加します。
d.Add "b", "Belgrade"
d.Add "c", "Cairo"
...


  Excel VBAでじゃんけんプログラム:多段ハッシュ(多段連想配列)を使った例
 http://d.hatena.ne.jp/bi_na/20100517/1274096780
 興味深い使い方の事例が、紹介されています。


 Item プロパティ は、Dictionary オブジェクトにある指定されたキーと関連付ける項目を設定します。
コレクションの場合、指定されたキーを基に項目を返します。値の取得も可能です。
 構文
 object.Item(key) [= newitem]

 Item プロパティの構文は、次の指定項目から構成されます。
指定項目 内容
Object 必ず指定します。Dictionary オブジェクトの名前を指定します。
Key 必ず指定します。取得または追加する項目と関連付けるキーを指定します。
Newitem 省略可能です。引数 key で指定した値と関連付ける新しい項目を指定します。

 注:.Item 部分を省略して記述することもできます。
 object(key) [= newitem]


 Key プロパティ は、Dictionary オブジェクトにキーを設定します。
値の取得も可能です。
 構文
 object.Key(key) = newkey

 Key プロパティの構文は、次の指定項目から構成されます。
指定項目 内容
object 必ず指定します。Dictionary オブジェクトの名前を指定します。
key 必ず指定します。変更するキーを指定します。
newkey 必ず指定します。引数 key で指定した値と置き換える新しいキーを指定します。


 CompareMode プロパティ は、Dictionary オブジェクトに文字列比較キーの比較モードを設定します。
値の取得も可能です。
 構文
 object.CompareMode[ = compare]

 CompareMode プロパティの構文は、次の指定項目から構成されます。
指定項目 内容
object 必ず指定します。Dictionary オブジェクトの名前を指定します。
compare 省略可能です。StrComp 関数などの関数を使って、比較モードを表す値を指定します。

 引数 compare には、次に示す定数の値を指定できます。
定数 内容
vbUseCompareOption -1 Option Compare ステートメントの設定を使用して比較を行います。
vbBinaryCompare 0 バイナリ モードで比較を行います。
vbTextCompare 1 テキスト モードで比較を行います。
vbDatabaseCompare 2 Microsoft Access の場合のみ有効。データベースに格納されている設定に基づいて比較を行います。

 既にデータが含まれている Dictionary オブジェクトの比較モードを変更しようとすると、エラーが発生します。
 CompareMode プロパティには、StrComp 関数の引数 compare の値と同じ値が使われます。2 より大きな値は、国別情報 (LCID) を使って比較を行うときに使われます。


 Exists メソッド は、指定されたキーが Dictionary オブジェクトの中に存在する場合は、真 (True) を返します。
存在しない場合は、偽 (False) を返します。
 構文
 object.Exists(key)

 Exists メソッドの構文は、次の指定項目から構成されます。
指定項目 説明
object 必ず指定します。Dictionary オブジェクトの名前を指定します。
key 必ず指定します。Dictionary オブジェクトの中から検索するキーの値を指定します。


 Keys メソッド は、Dictionary オブジェクトにあるすべてのキーに含まれる配列を返します。
 構文
 object.Keys

 object には、Dictionary オブジェクトの名前を指定します。

 次のコードは、Keys メソッドの使用例です。

Dim a, d, i             '複数の変数を作成します。
Set d = CreateObject("Scripting.Dictionary")
d.Add "a", "Athens"     '複数のキーと項目を追加します。
d.Add "b", "Belgrade"
d.Add "c", "Cairo"
a = d.keys              'キーを取得します。
For i = 0 To d.Count -1 '配列を繰り返します。
    Print a(i)          'キーを印刷します。
Next
...


 Items メソッド は、Dictionary オブジェクトのすべての項目に含まれる配列を返します。
 構文
 object.Items

 object には、Dictionary オブジェクトの名前を指定する必要があります。

 次のコードは、Items メソッドの使用例です。

Dim a, d, i             '複数の変数を作成します。
Set d = CreateObject("Scripting.Dictionary")
d.Add "a", "Athens"     '複数のキーと項目を追加します。
d.Add "b", "Belgrade"
d.Add "c", "Cairo"
a = d.Items             '項目を取得します。
For i = 0 To d.Count -1 '配列を繰り返します。
    Print a(i)          '項目を印刷します。
Next
...


 Add メソッド (Dictionary オブジェクト) は、Dictionary オブジェクトにキーと対の項目を追加します。
 構文
 object.Add key, item

 Add メソッドの構文は、次の指定項目から構成されます。
指定項目 説明
Object 必ず指定します。Dictionary オブジェクトの名前を指定します。
Key 必ず指定します。追加する引数 item と関連付けられた引数 key を指定します。
Item 必ず指定します。追加する引数 key と関連付けられた引数 item を指定します。

 引数 key での指定が既に存在している場合は、エラーとなります。


 RemoveAll メソッド は、Dictionary オブジェクト内のすべてのアイテムを削除します。


 下は、上の処理に使う、サンプル・データを生成するためのマクロです。

Option Explicit
Option Base 1

   Dim カウンタ As Integer
   Dim 一桁目 As Integer
   Dim 二桁目 As Integer
   Dim 三桁目 As Integer

Sub サンプルデータ準備()

   Call 品目マスタ捏造
   Call 注文リスト捏造
   ThisWorkbook.Worksheets("スタート").Activate
   
End Sub

Private Sub 品目マスタ捏造()

   Dim 仕入先配列 As Variant
   Dim 仕入先件数 As Integer
   
   ThisWorkbook.Worksheets("仕入先マスタ").Activate
   仕入先配列 = Range("A1").CurrentRegion
   仕入先件数 = UBound(仕入先配列) - 1 '一行目は項目名のため除外
   
   ThisWorkbook.Worksheets("品目マスタ").Activate
   
   カウンタ = 0
   For 一桁目 = 1 To 26
      For 二桁目 = 1 To 26
         For 三桁目 = 1 To 26
            カウンタ = カウンタ + 1
            If カウンタ > 15000 Then Exit For
            Range("A2").Cells(カウンタ, 1).Value _
            = Chr(64 + 一桁目) & Chr(64 + 二桁目) & Chr(64 + 三桁目) '品目コード
            Range("B2").Cells(カウンタ, 1).Value = 仕入先配列(Int(Rnd() * 仕入先件数) + 2, 1)
            Range("C2").Cells(カウンタ, 1).Value = (Int(Rnd() * 1000) + 1) * 10  '単価
            Range("D2").Cells(カウンタ, 1).Value = (Int(Rnd() * 100) + 1) * 10   '重量
         Next 三桁目
      Next 二桁目
   Next 一桁目
End Sub


Private Sub 注文リスト捏造()
   
   ThisWorkbook.Worksheets("注文リスト").Activate
   
   For カウンタ = 1 To 10000
      Range("A2").Cells(カウンタ, 1).Value _
      = Chr(64 + Int(Rnd() * 26) + 1) & Chr(64 + Int(Rnd() * 26) + 1) & Chr(64 + Int(Rnd() * 26) + 1) '品目コード
      Range("B2").Cells(カウンタ, 1).Value = Int(Rnd() * 100) + 1
   Next カウンタ
End Sub

この種類の目次に戻る↑ 索引へ↓ トップページに戻る


Dictionary オブジェクトと Collection オブジェクト

 Dictionary オブジェクトは、Collection オブジェクトと似ていますが、Dictionary オブジェクトには Collection オブジェクトにない、次のような特定の機能が含まれます。
 Collection オブジェクトに対する Dictionary オブジェクトの主な利点は、アイテムの Dictionary オブジェクトは検索が簡単であるということです。
 この利点にもかかわらず、Dictionary オブジェクトを Collection オブジェクトの代わりにすべて使用することはできません。Dictionary オブジェクトより Collection オブジェクトのほうが役に立つ場合もあります。
 たとえば、カスタム オブジェクト モデルを作成する場合、Collection オブジェクトを使用してカスタム コレクションへの参照を保存することができますが、Dictionary オブジェクトではこの操作は行えません。カスタム オブジェクト モデルの作成については、「カスタム クラスとオブジェクト」を参照してください。

 下記にも、Collection オブジェクトと Dictionary オブジェクトを比較したコード例を掲示していただいています。
 Dictionary オブジェクトに関するメモ
http://www.f3.dion.ne.jp/~element/msaccess/AcResTipsWarehouse1.html


 Collection オブジェクト は、1 つのオブジェクトとして参照できる複数の要素の集合です。

 Collection オブジェクトを利用すると、互いに関連付けられた複数の要素を 1 つのオブジェクトとして参照できます。
コレクションの要素、またはメンバはコレクション内に存在することにより関連付けられています。
コレクションのメンバは、同じデータ型を共有する必要はありません。

 Collection オブジェクトは、他のオブジェクトと同じ方法で作成できます。たとえば、次のように宣言します。
Dim X As New Collection
 作成した Collection オブジェクトにメンバを追加するときには Add メソッドを使い、メンバを削除するときには Remove メソッドを使います。
また、Collection オブジェクトから特定のメンバを取得するときには Item メソッドを使い、Collection オブジェクトに含まれるすべてのメンバを取得するときには For Each ... Next ステートメントを使います。

 次の例は、Collection オブジェクト (MyClasses) を作成した後、このコレクションにオブジェクトを追加するためのダイアログ ボックスを表示します。
このプログラムを実行するには、まず、[挿入] - [クラス モジュール] をクリックしてから、各インスタンスの名前を格納するパブリック変数 InstanceName を Class1 のモジュール レベルで宣言します (「Public InstanceName」と入力)。
モジュール名は、既定値の Class1 のまま変えないでください。
下のコードをコピーし、別のモジュールの宣言セクションにコードを貼り付け、他のプロシージャの ClassNamer ステートメントで起動します。
この例では、ホスト アプリケーションがクラスをサポートする場合のみ実行できます。

Sub ClassNamer()
    Dim MyClasses As New Collection    ' Collection オブジェクトを作成します。
    Dim Num                            ' 個々のインスタンスを区別するためのカウンタを宣言します。
    Dim Msg As String                  ' メッセージ用の文字列を格納する変数を宣言します。
    Dim TheName, MyObject, NameList    ' 情報を格納するバリアント型の変数を宣言します。

    Do
        Dim Inst As New Class1         ' Class1 の新しいインスタンスを作成します。
        Num = Num + 1                  ' 変数 Num を加算した後、インスタンスの名前を取得します。
        Msg = "このオブジェクトの名前を入力してください。" & Chr(13) _
         & "コレクション内のオブジェクトの名前を確認するには、キャンセル ボタンを押してください。"
        TheName = InputBox(Msg, "コレクション アイテムの名前付け")
        Inst.InstanceName = TheName    ' オブジェクトのインスタンスに名前を代入します。

        ' ユーザーが名前を入力した場合は、オブジェクトをコレクションに追加します。
        If Inst.InstanceName <> "" Then
            ' 名前を付けたオブジェクトをコレクションに追加します。
            MyClasses.Add item := Inst, key := CStr(Num)
        End If

        ' 次の参照の準備のため、現在の参照内容をクリアします。
        Set Inst = Nothing
    Loop Until TheName = ""

    For Each MyObject In MyClasses     ' インスタンスの名前の一覧を作成します。
        NameList = NameList & MyObject.InstanceName & Chr(13)
    Next MyObject

    ' メッセージ ボックスにインスタンスの名前の一覧を表示します。
    MsgBox NameList, , "MyClasses コレクション内のインスタンスの名前"

    For Num = 1 To MyClasses.Count     ' コレクションからオブジェクトの名前を削除します。
        MyClasses.Remove 1             ' コレクションは自動的にインデックスが付け直されるので、
                                       ' ループを繰り返すごとに先頭のメンバを削除します。
    Next
End Sub

この種類の目次に戻る↑ 索引へ↓ トップページに戻る


ホームページのトップに戻る