【2026年8月最新】VBA Collectionオブジェクトの使い方完全ガイド|宣言・Add・Item・Remove・存在チェックまで実務コードで解説
Excelマクロを組んでいて、「同じ種類のデータを複数まとめて持っておきたいけど、配列だと要素数が変わるたびにReDimするのが面倒…」と感じたことはありませんか。
その悩みを解決してくれるのがCollection(コレクション)オブジェクトです。VBA標準の機能でありながら、配列よりも柔軟にデータをまとめて管理でき、「名前(キー)で要素を呼び出す」という配列にはできない芸当も可能にします。
この記事では、Collectionオブジェクトの宣言・Add・Item・Count・For Each・存在チェック・Removeという一連の操作を、実務でそのまま使えるコード付きで解説します。さらに、似た機能を持つScripting.Dictionaryとの使い分け、そして弊社(株式会社GENAI)の実運用データをもとにした「VBAを書かずに済ませる」という選択肢まで、非エンジニアの方にも分かりやすく整理しました。
この記事を最後まで読むと、次の7つが明確になります。
01 COLLECTION BASICS Collectionオブジェクトとは?配列との違い 「複数のデータをまとめて持つ」ための2つの選択肢を比較する
Collectionオブジェクトは、VBAに標準搭載されているオブジェクトで、複数のデータをひとまとめにして管理するための入れ物です。参照設定なども不要で、いつでもDimとNewの2行で使い始められます。
📚 用語解説
Collectionオブジェクト:複数の値やオブジェクトをひとまとめに格納できるVBA標準のデータ構造。配列と違い、要素数をあらかじめ決める必要がなく、Addで追加、Removeで削除、Itemで取得、Countで件数取得ができる。要素ごとに「キー(名前)」を付けて名前で呼び出すこともできる。
「複数のデータをまとめて扱う」という目的だけを見ると配列(Array)と似ていますが、性質はかなり違います。まずは代表的な違いを表で整理します。
| 比較項目 | 配列(Array) | Collectionオブジェクト |
|---|---|---|
| 要素数の変更 | 固定長は不可。可変長でもReDim(Preserveで保持)が必要 | Add / Removeでいつでも自由に増減できる |
| 格納できる型 | 基本は同じ型で統一(Variant型なら混在可) | 型を問わず混在可能(文字列・数値・オブジェクトを同じCollectionに入れられる) |
| インデックスの起点 | 既定は0始まり(Option Baseで変更可) | 常に1始まり |
| 名前(キー)でのアクセス | 不可 | Addの際にKeyを指定すれば、Item("キー名")で取得できる |
| 要素数の取得 | UBound関数で計算(LBoundとの差分に注意が必要) | Countプロパティで直接取得できる |
| 存在チェック | 該当なし(ループで探すしかない) | 専用メソッドはない(後述する代用パターンが必要) |
1-1. Collectionが向いている場面
Collectionは、次のような場面で配列よりも書きやすくなります。
「要素数が事前に分かっていて、とにかく高速に大量データを処理したい」なら配列。「要素数が読めない・キーで呼び出したい・途中で追加削除したい」ならCollection、というのが実務での基本的な判断基準です。数万行単位の高速処理が必要な場面では、配列に一括読み込みしてから処理するほうが速いケースが多い点も覚えておくと安心です。
02 DECLARE & ADD 宣言とAddメソッドの基本構文 Dim → New → Addという3ステップを実例で押さえる
Collectionを使うときの基本の流れは、「宣言する(Dim)」→「実体を作る(New)」→「要素を追加する(Add)」の3ステップです。まずは顧客リストを例に、コードを見てみましょう。
Sub AddCustomers()
Dim custList As Collection
Set custList = New Collection
custList.Add "田中商事", "C001"
custList.Add "佐藤物産", "C002"
custList.Add "鈴木工業", "C003"
MsgBox "登録件数: " & custList.Count ' 3 と表示される
End Sub
Dim custList As Collectionで変数を宣言し、Set custList = New Collectionで実体(インスタンス)を作成します。この「New」を書き忘れると、Addを呼んだ瞬間に実行時エラーになるので注意してください(詳しくは第9章で解説します)。
📚 用語解説
オブジェクト変数とNewキーワード:Collectionのようなオブジェクト型の変数は、Dimで「宣言」しただけでは中身が空(Nothing)の状態です。New(またはCreateObject)で実体を作り、Setでその実体を変数に代入して初めて使えるようになる。「Dim custList As Collection」だけではまだ使えず、「Set custList = New Collection」まで書いて初めて機能する点が、文字列や数値の変数との大きな違い。
2-1. Addメソッドの引数:Item・Key・Before・After
AddメソッドはAdd(Item, Key, Before, After)という4つの引数を持ちます。Itemだけは必須で、残りの3つは省略可能です。
| 引数 | 役割 | 省略した場合 |
|---|---|---|
| Item | 追加する値やオブジェクト(必須) | (省略不可) |
| Key | 要素に付ける一意の名前(文字列) | キーなしの要素になり、インデックスでしか取得できない |
| Before | 指定した位置(インデックス or キー)の直前に挿入 | 末尾に追加される |
| After | 指定した位置(インデックス or キー)の直後に挿入 | 末尾に追加される |
Sub AddWithPosition()
Dim custList As Collection
Set custList = New Collection
custList.Add "田中商事", "C001"
custList.Add "佐藤物産", "C002"
' "C002"の直前に"山田商会"を挿入する
custList.Add "山田商会", "C004", Before:="C002"
Dim c As Variant
For Each c In custList
Debug.Print c ' 田中商事 → 山田商会 → 佐藤物産 の順で出力
Next c
End Sub
Addの第2引数Keyには文字列(String)しか指定できません。また、同じKeyを持つ要素を2回Addしようとすると実行時エラー457「このキーは既にこのコレクションの要素と関連付けられています」が発生します。同じ顧客コードで2回登録しようとする、といった業務データではよくあるミスなので、事前の重複チェック(第5章)を組み合わせるのが安全です。
03 ITEM & COUNT Item・Countで要素を取得する方法 インデックス指定とキー指定、2通りのアクセス方法を使い分ける
Collectionから値を取り出すにはItemメソッドを使います。Itemには「インデックス(何番目か)」と「キー(登録時に付けた名前)」の2種類の指定方法があります。
Sub GetCustomer()
Dim custList As Collection
Set custList = New Collection
custList.Add "田中商事", "C001"
custList.Add "佐藤物産", "C002"
MsgBox custList.Item(1) ' 田中商事(インデックス指定・1始まり)
MsgBox custList.Item("C002") ' 佐藤物産(キー指定)
MsgBox custList(1) ' 田中商事(Itemは既定メンバーなので省略できる)
End Sub
📚 用語解説
既定メンバー(デフォルトプロパティ):オブジェクトの中で「呼び出し名を省略しても呼ばれるメンバー」のこと。CollectionではItemが既定メンバーに設定されているため、「custList.Item(1)」と「custList(1)」はまったく同じ結果になる。コードの可読性を重視する現場では、あえてItemを省略せずに書くスタイルもよく使われる。
要素数を数えたいときはCountプロパティを使います。配列のようにUBoundとLBoundを引き算する必要がなく、そのまま件数が返ってくるのがCollectionの分かりやすい点です。
Sub ShowCount()
Dim custList As Collection
Set custList = New Collection
custList.Add "田中商事", "C001"
custList.Add "佐藤物産", "C002"
custList.Add "鈴木工業", "C003"
MsgBox "登録件数: " & custList.Count ' 3
End Sub
04 FOR EACH LOOP For Each文でCollectionをループ処理する 登録した順番に全要素を処理する、もっとも実務で使う書き方
Collectionの全要素を順番に処理したいときはFor Each文を使うのが定番です。インデックスを意識せずに書けるので、配列よりもシンプルなコードになります。
Sub ListAllCustomers()
Dim custList As Collection
Dim c As Variant
Set custList = New Collection
custList.Add "田中商事", "C001"
custList.Add "佐藤物産", "C002"
custList.Add "鈴木工業", "C003"
For Each c In custList
Debug.Print c
Next c
' 出力順: 田中商事 → 佐藤物産 → 鈴木工業(Addした順)
End Sub
For Each文はAddした順番で要素を取り出します。Collectionは常に1始まりのインデックスを内部で保持しているため、順序が入れ替わることはありません(Before/Afterで挿入位置を指定した場合はその位置が反映されます)。
宣言
Dim col As Collection
初期化
Set col = New Collection
追加
col.Add 値, キー
取得・処理
Item / For Each
削除
col.Remove
この「宣言→初期化→追加→取得・処理→削除」という5ステップが、Collectionを使うマクロの基本骨格になります。まずはこの流れを型として覚えてしまうと、応用が効きやすくなります。
For Each文で取り出した変数(上の例ではc)に値を代入しても、元のCollectionの中身は変わりません。Collectionの中身自体を書き換えたい場合は、いったんRemoveしてから新しい値でAddし直す必要があります。
05 EXISTENCE CHECK 要素の存在チェックをする方法 Collectionには「Exists」がない。On Error Resume Nextで代用する
ここがCollectionを使う上で最初につまずきやすいポイントです。Collectionには「このキーは存在するか」を判定する専用メソッドがありません。後述するScripting.DictionaryにはExistsメソッドがあるため混同しがちですが、Collectionでは別の方法で代用する必要があります。
📚 用語解説
On Error Resume Next:VBAのエラー処理構文の1つ。この行以降、エラーが発生してもプログラムを止めずに次の行へ処理を進める。エラーの有無は「Err.Number」(エラーが起きていなければ0)で判定できる。エラーを握りつぶして無視するために使うと不具合の温床になるため、「意図的にエラーを検知したい1行だけ」に限定して使うのが安全な作法。
存在しないキーをItemで指定すると実行時エラー5「プロシージャの呼び出しまたは引数が不正です」が発生します。このエラーを逆手にとって、「エラーが起きなければ存在する、起きれば存在しない」と判定するのが定番の代用パターンです。
Function KeyExists(col As Collection, ByVal key As String) As Boolean
Dim tmp As Variant
On Error Resume Next
Err.Clear
tmp = col.Item(key)
On Error GoTo 0
KeyExists = (Err.Number = 0)
End Function
Sub CheckExample()
Dim custList As Collection
Set custList = New Collection
custList.Add "田中商事", "C001"
MsgBox KeyExists(custList, "C001") ' True
MsgBox KeyExists(custList, "C999") ' False
End Sub
On Error Resume Nextを書いた直後にErr.Clearを呼ばずにItemを実行すると、直前の別の処理で起きた古いエラー番号が残っていて、実際には存在するキーなのに「存在しない」と誤判定することがあります。存在チェックの関数は必ずErr.Clear→実行→判定、の順番で書いてください。
06 REMOVE Removeで要素を削除する(インデックスのズレに注意) 削除後は後ろの要素のインデックスが1つずつ詰まる
要素を削除するにはRemoveメソッドを使います。Itemと同じく、インデックス指定・キー指定の両方に対応しています。
Sub RemoveCustomer()
Dim custList As Collection
Set custList = New Collection
custList.Add "田中商事", "C001"
custList.Add "佐藤物産", "C002"
custList.Add "鈴木工業", "C003"
custList.Remove "C002" ' キー指定で削除
MsgBox custList.Count ' 2
MsgBox custList.Item(2) ' 鈴木工業(削除後にインデックスが1つ詰まる)
End Sub
削除前は「田中商事(1)・佐藤物産(2)・鈴木工業(3)」という並びでしたが、佐藤物産(キーC002)を削除すると、鈴木工業のインデックスは3から2に繰り上がります。これがCollectionの落とし穴で、ループしながら削除する処理を書くと、意図せず要素を読み飛ばすバグを生みやすい部分です。
「For i = 1 To col.Count」で回しながらcol.Remove(i)を呼ぶと、削除のたびに後続の要素のインデックスが詰まり、次のiで本来処理すべき要素をスキップしてしまいます。安全に書くには後ろのインデックスから逆順に削除する(For i = col.Count To 1 Step -1)か、削除対象のキーを別のCollectionや配列にいったん貯めてから、最後にまとめて削除する方法をおすすめします。
' 安全な書き方:逆順に削除する
Sub RemoveOldRecords()
Dim custList As Collection
Dim i As Long
Set custList = New Collection
custList.Add "田中商事", "C001"
custList.Add "(退会)佐藤物産", "C002"
custList.Add "(退会)鈴木工業", "C003"
For i = custList.Count To 1 Step -1
If InStr(custList.Item(i), "(退会)") > 0 Then
custList.Remove i
End If
Next i
MsgBox custList.Count ' 1(田中商事だけが残る)
End Sub
07 COLLECTION VS DICTIONARY 【独自】CollectionとDictionaryの使い分け 「名前で呼び出したい」が本格化したらDictionaryも検討する
ここからは競合記事にはない独自の切り口として、Collectionとよく比較されるScripting.Dictionary(連想配列)との使い分けを整理します。「存在チェックができない」という第5章の弱点は、実はDictionaryなら標準機能で解決できます。
📚 用語解説
Scripting.Dictionary:Microsoft Scripting Runtimeが提供する連想配列(キーと値のペアを管理するオブジェクト)。CreateObject("Scripting.Dictionary")で参照設定なしに使える(遅延バインディング)。Existsメソッドで存在チェックができる、Keysメソッドで全キーを一括取得できるなど、Collectionにない機能を多く備えるが、VBA標準機能ではなく外部ライブラリ(Windows標準搭載のscrrun.dll)に依存する点がCollectionとの違い。
📚 用語解説
ハッシュテーブル:キーから値を高速に探し出すためのデータ構造。Dictionaryの内部実装に使われているとされ、データ件数が増えてもキー検索の速度が大きく落ちにくいという特性を持つ。Collectionはこの仕組みを持たないため、キーで探す処理を大量に繰り返す場面ではDictionaryの方が有利になりやすい。
| 比較項目 | Collection | Scripting.Dictionary |
|---|---|---|
| 参照設定・生成方法 | VBA標準機能、参照設定不要 | CreateObject("Scripting.Dictionary")の遅延バインディングか、「Microsoft Scripting Runtime」の参照設定が必要 |
| 存在チェック | 標準メソッドなし(On Error等で代用が必要) | Existsメソッドで一発判定できる |
| キーの型 | 文字列のみ | 数値・文字列など柔軟に指定できる |
| キーの変更 | 不可(削除して再Addするしかない) | .Key(旧キー) = 新キー で変更できる |
| 全キーの一括取得 | ループで1件ずつ確認するしかない | Keysメソッドで配列として一括取得できる |
| インデックス指定でのアクセス | Item(数値)で可能 | 原則不可(キー指定が基本) |
7-1. どちらを選ぶべきか:3つの判断軸
最初の設計段階で完璧に選び分ける必要はありません。実務では「Collectionで書き始めたが、If文での存在チェックがどんどん増えてコードが読みにくくなってきた」タイミングでDictionaryに書き換える、という進め方が現実的です。
08 GENAI CASE DATA 【独自】GENAI実運用データで見るVBA業務のAI化 VBAで自動化するか、Claude Codeにそもそも任せるか
ここまでCollectionオブジェクトの文法を細かく解説してきましたが、視点を少し引いて考えてみます。VBAマクロを組むこと自体、すでに「業務効率化」の一種です。では、その効率化をさらに一段引き上げる手段はあるのでしょうか。
弊社(株式会社GENAI)では、Claude Max 20xプラン(月額$200・約30,000円)を契約し、経営・営業・広告・開発・経理・秘書業務まで全社的にClaude Codeを活用しています。VBAコードの作成・修正はもちろん、そもそもExcelマクロを介さずに業務を自動化できるケースも増えています。
| 業務領域 | 主な用途 | 削減時間(概算・肌感ベース) |
|---|---|---|
| 営業 | 提案書・見積・顧客別資料の自動生成 | 週20h → 週2h |
| 広告運用 | 週次レポート・CPA分析・配信内容調整 | 週10h → 週1h |
| 経理 | 請求書チェック・経費仕訳・Freee連携 | 月40h → 月5h |
| 秘書業務 | 日報生成・議事録・スケジュール調整 | 日2h → 日15分 |
| 開発 | Excel VBAマクロ・スクリプトの書き捨て生成 | 都度数時間削減 |
上記は弊社の肌感ベースの数値であり、業種・業態・担当者のスキルによって削減時間は変動します。「Claude Codeを業務に組み込むとどの程度まで使い倒せるか」の参考情報としてご覧ください。
注目したいのは「開発」領域です。Collectionを使ったVBAマクロのような、要素の追加・削除・存在チェックを組み合わせる処理は、条件が複雑になるほど手で書く時間がかかります。この記事の第5章・第6章で扱った「存在チェックの代用パターン」「削除時のインデックスのズレ」のような落とし穴も、Claude Codeに要件を伝えれば、あらかじめ対策済みのコードとして生成されます。
「顧客リストを重複なく
管理したい」など
自然言語で指示
「VBAで書いて」と
話しかけるだけ
して実行
生成されたマクロを
試しに動かす
横展開
問題なければ
他業務にも適用
この4ステップを回すことで、VBAの文法を1行1行暗記していなくても、「何をしたいか」を言葉で伝えるだけで実務レベルのマクロが手に入ります。もちろん、生成されたコードをそのまま鵜呑みにせず、動作確認とレビューを挟むことは必須です。
09 COMMON ERRORS よくあるエラーと対処法5選 Collectionを使う中で実際によく遭遇するつまずきポイント
最後に、Collectionを使う中で実際によく遭遇するエラーと、そのつまずきポイントを一覧で整理します。エラー番号を知っておくと、次に同じエラーに遭遇したときの原因特定が速くなります。
| エラー番号 | エラー内容 | 典型的な原因 | 対処法 |
|---|---|---|---|
| 実行時エラー91 | オブジェクト変数With ブロック変数が設定されていません | Dim col As Collectionの後にSet col = New Collectionを書き忘れている | Newで必ず初期化してから使う。宣言と初期化はセットで書く習慣をつける |
| 実行時エラー457 | このキーは既にこのコレクションの要素と関連付けられています | 同じKeyでAddを2回呼んでいる(Keyは一意である必要がある) | 第5章のKeyExists関数などでAdd前に重複チェックを行う |
| 実行時エラー438 | オブジェクトはこのプロパティまたはメソッドをサポートしていません | col.Exists()のように、Dictionary専用のメソッドをCollectionに対して呼んでいる | 存在チェックが必要ならOn Error Resume Nextで代用するか、最初からScripting.Dictionaryを使う |
| 実行時エラー5 | プロシージャの呼び出しまたは引数が不正です | 存在しないキーや範囲外のインデックスをItemで指定している | 事前に存在チェックを行うか、On Error Resume Nextでエラーを捕捉する |
' 実行時エラー91の例(New忘れ)
Sub ObjectNotSetExample()
Dim col As Collection
col.Add "サンプル" ' ← 実行時エラー91が発生する(Set col = New Collectionがない)
End Sub
5つ目の「エラー」は、正確には実行時エラーではなくロジックバグです。第6章で解説した、ループしながらRemoveすると要素の読み飛ばしが起きる問題です。エラーメッセージが出ないぶん発見が遅れやすく、実務では最も見つけにくい不具合の1つと言えます。
10 CONCLUSION まとめ ── Collectionを使いこなす・使わずに済ませる VBAの文法を覚える道と、AIに任せる道の両方を知っておく
この記事では、VBA Collectionオブジェクトの基本構文から、配列・Dictionaryとの違い、実務で踏みやすいエラーまでを整理しました。最後にポイントを振り返ります。
Collectionオブジェクトは、覚えてしまえば非常に扱いやすいVBAの武器です。一方で、この記事で紹介した「存在チェックの代用」「削除時のインデックスのズレ」のような細かい落とし穴は、VBA初学者が独力でハマりやすいポイントでもあります。
文法を1つずつ覚えて自分で書けるようになる道もあれば、要件を言葉で伝えてAIにコードを生成させる道もあります。どちらが正しいということはなく、状況に応じて使い分けるのが現実的です。
VBAマクロの作成・改修も、Claude Codeで自動化できます
「Collectionを使った顧客リスト管理マクロを作りたい」「既存のVBAコードでエラーが出て解決できない」——こうしたExcel VBAの課題は、Claude Codeに要件を日本語で伝えるだけで解決できます。
まずは無料相談で、貴社のExcel業務のどこにAIを組み込めるか、具体的にお答えします。
NEXT STEP
この記事の内容を、あなたのビジネスで
実践してみませんか?
よくある質問
Q. VBAのCollectionと配列(Array)、結局どちらを使えばいいですか?
A. 要素数が事前に分かっていて大量データを高速処理したいなら配列、要素数が読めない・キーで呼び出したい・途中で追加削除したいならCollectionが向いています。数万行規模のセル処理は配列に一括読み込みしてから処理する方が速いケースが多く、少量のリストを柔軟に管理したい場合はCollectionが書きやすい、というのが実務での基本的な使い分けです。
Q. Collectionで要素の存在チェックをする一番簡単な方法は?
A. CollectionにはExistsのような専用メソッドがないため、On Error Resume Next + Err.Clearを使い、存在しないキーをItemで取得したときに発生する実行時エラー5を検知する方法が定番です。記事内で紹介したKeyExists関数のように、汎用の判定関数を1つ用意しておくと、Add前の重複チェックや削除前の存在確認に使い回せます。
Q. Collectionのキーは数値でも指定できますか?
A. できません。Addメソッドの第2引数Keyには文字列(String型)しか指定できない仕様です。数値をキーにしたい場合は「CStr(番号)」のように文字列へ変換してから渡す必要があります。数値のままキーに指定しようとするとコンパイルエラーまたは実行時エラーになるため注意してください。
Q. Removeで要素を削除した後、インデックス番号はどうなりますか?
A. 削除した要素より後ろにあった要素は、インデックスが1つずつ繰り上がります。例えば3件のうち2番目を削除すると、元3番目だった要素が2番目になります。ループしながらRemoveする処理を書く場合、この繰り上がりによって要素を読み飛ばすバグが起きやすいため、後ろのインデックスから逆順に削除するのが安全です。
Q. Scripting.Dictionaryを使うには参照設定が必要ですか?
A. 必須ではありません。「CreateObject("Scripting.Dictionary")」と書けば、参照設定なし(遅延バインディング)でも利用できます。コード補完(入力候補)を効かせたい場合は「Microsoft Scripting Runtime」への参照設定(早期バインディング)を行う方法もありますが、他の担当者のPCで参照設定が外れていると動かなくなるリスクがあるため、配布するマクロでは遅延バインディングを使うケースが多いです。
Q. For Each文でCollectionをループ処理しながら要素を削除しても安全ですか?
A. 安全ではありません。For Each中に要素を削除すると、内部のインデックスがずれて意図しない要素がスキップされることがあります。安全に削除したい場合は、For Each ではなく「For i = col.Count To 1 Step -1」のように、後ろから前へ向かってインデックスでループしながらRemoveする書き方に変更してください。
Q. VBAが苦手でも、Collectionを使うような処理を自動化できますか?
A. できます。Claude CodeのようなAIエージェントに「顧客コードをキーにして重複なく登録・検索できるリストをVBAで作って」のように要件を日本語で伝えるだけで、Collection(またはDictionary)を使った実務レベルのコードが生成されます。弊社GENAIでもClaude Max 20xプラン(月額約30,000円)を契約し、VBAコードの生成やデバッグに日常的に活用しています。文法を覚える前に、まず生成されたコードを動かしてみるという学び方も有効です。
Claude Codeで業務自動化を90日で叩き込む
経営者向けの伴走型パーソナルトレーニング
AI鬼管理へのお問い合わせ
この記事を読んで気になった方へ。
AI鬼管理の専門スタッフが、御社に最適な
業務自動化プランを無料でご提案します。




