🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA の New — オブジェクトの生成、New と CreateObject、そして Dim As New の罠

|

Excel VBA の New — オブジェクトの生成、New と CreateObject、そして Dim As New の罠

TL;DRNew はオブジェクトを存在させます。Set d = New Dictionary はまっさらで空の Dictionary を作り、d をそこへ向けます。New事前バインディング — ライブラリの参照設定が要る代わりに、 IntelliSense、コンパイル時のチェック、そして速度が手に入ります。CreateObject遅延バインディング — 参照設定なし、実行時に解決され、マシンをまたいで可搬です。そして Dim d As New Dictionary は避けましょう。オブジェクトを遅延生成し、解放したあとも静かによみがえらせ ます。Dim d As Dictionary としてから Set d = New Dictionary とするのが得策です。

Sub CreateAnInstance()
    ' 事前バインディング - Tools > References > Microsoft Scripting Runtime
    Dim d As Dictionary
    Set d = New Dictionary                        ' New は真新しい空の Dictionary を作る
    d.Add "a", 1

    ' 遅延バインディング - 参照設定なし、実行時に解決、可搬性あり
    Dim late As Object
    Set late = CreateObject("Scripting.Dictionary")
End Sub

New はオブジェクトのライフサイクルにおける「誕生」の段階です。New がオブジェクトを作り、 Set が変数をそこへ向け、Nothing が解放します。Set が ラベルを どの オブジェクトに向けるかを決めるのに対し、New は真新しいものがそもそも存在するに至るか どうかを決めます。

この記事で学べること

  • 考え方の軸 — New はコンストラクタ、オブジェクトが生まれる瞬間である
  • NewCreateObject — 事前バインディングと遅延バインディング、それぞれが勝つ場面
  • Dim As New の罠 — 遅延生成と、Nothing のあとに自らよみがえるオブジェクト
  • なぜ New 一つはインスタンス一つを意味し、ループ内の New は何をするのか
  • New できるもの、できないもの(自作のクラスモジュールや Dictionary はできる、Worksheet はできない)

考え方の軸:New は誕生の瞬間

クラスやライブラリは 設計図 を与えます。New はそこから物理的な インスタンス を一つ打ち出します。 Set d = New Dictionary は、一行に書かれた二つの手順です。New Dictionary が新しい空の dictionary をメ モリ上に作り、Set d = が変数 d をそこへ向けます。右から左へ読んでください — オブジェクトがまず作ら れ、それからラベルが取り付けられるのです。

これが NewSet 単体との違いです。Set ws = Worksheets("Data") は、すでに存 在する シートにラベルを向けます。新しいものは何も作られません。Set d = New Dictionary は、指し示す前 にオブジェクトを 作ります。まっさらで空のオブジェクトが欲しいなら New(または CreateObject)が要 り、すでに存在するものを参照したいだけなら Set だけで足ります。

New と CreateObject:事前バインディングと遅延バインディング

外部のオブジェクトを作る方法は二つあり、その選択は実のところ、事前バインディングと遅延バインディングの どちらを取るかという選択です。

' 事前バインディング - New - 参照設定にチェックが要る、IntelliSense + コンパイルチェックが効く
Dim d As Dictionary
Set d = New Dictionary

' 遅延バインディング - CreateObject - 参照設定なし、実行時に解決、可搬性あり
Dim d As Object
Set d = CreateObject("Scripting.Dictionary")

New(事前バインディング) は、Tools ▸ References からライブラリを追加しておくことを求めます (Dictionary なら Microsoft Scripting Runtime)。その見返りに、入力しながら IntelliSense が効き、実行 前にコンパイラが綴りミスのメソッドを捕まえ、呼び出しがわずかに速くなります。代償はこうです。その参照設 定が欠けている、あるいはバージョンの違うマシンにブックを渡すと、Can't find project or library で壊れる ことがあります。

CreateObject(遅延バインディング) は、参照設定をまったく必要としませ ん — 変数を As Object で宣言し、クラス名を文字列で指定すれば、VBA が実行時に解決します。これにより、ブ ックはバージョンやマシンをまたいで可搬になります。代わりに IntelliSense はなく、呼び出しはわずかに遅くな ります。目安はこうです。手元で管理し、ツール支援が欲しいマシンで動くコードには New。広く配布するコード には CreateObject。

Dim As New の罠

Dim d As New Dictionary は、宣言と生成を一行にまとめた、きれいな近道に見えます。ですがこれは避けるべき 唯一の書き方であり、その三つの理由はすべて同じ振る舞いにたどり着きます。VBA は Dim の時点でオブジェ クトを作りません。最初に使ったときに遅延生成し、使うたびに再チェックするのです。

Dim d As New Dictionary        ' 便利そうに見える - でもオブジェクトはまだ作られていない
' ... のちほど ...
d.Add "a", 1                   ' ここで初めて、最初のアクセス時に VBA が黙って作る
  1. 遅延生成され、アクセスのたびに隠れたチェックが入る。 d を使うたび、その裏で VBA は「もし d が Nothing なら作る」という見えないテストを差し込みます。小さいとはいえ、参照のたびに毎回走ります。
  2. Is Nothing を確実にテストできない。 If d Is Nothing と書いた瞬間、d に触れる行為そのものがそ の自動生成を引き起こすので、テストは事実上つねに False になります。「これは一度でも設定されたのか?」 と問う力を失うのです。
  3. 解放したあとに自らよみがえる。 Set d = Nothing はオブジェクトを解放するように見えますが、次に d に触れた途端、VBA は 新しい 空のものを作ります。本当に手放すことが決してできないのです。

直し方は、宣言と生成を分けることです。こちらのほうが読んでも明快です。

Dim d As Dictionary            ' 型を宣言する - d は Nothing から始まる
Set d = New Dictionary         ' 作りたいと思ったそのときに作る

New 一つにつきインスタンス一つ

New は実行のたびに 一つ のオブジェクトを作ります。これが最も効いてくるのがループの中です。反復ごとに まっさらなオブジェクトが必要なら — たとえば行ごとに新しいクラスインスタンスが要るなら — New をループの 内側に置きます。

Dim i As Long, item As clsLineItem
For i = 1 To 100
    Set item = New clsLineItem     ' 毎回、真新しいオブジェクト
    item.Load rows(i)
    log.Add item
Next i

各周回が新しい clsLineItem を作り、前のものは log の中で生き続けます。もし代わりにループの 前で 一 度だけ New して同じオブジェクトを使い回すと、log のすべての要素が、最後の行のデータを保持する 同じ インスタンスを指すことになります — 「レコードが全部同じになる」という典型的なバグです。

New できるもの、できないもの

New できるのは、自作のクラスモジュールと、Dictionary(参照設定つき)のような生成可能なライブラリのク ラス、そして組み込みの CollectionNew Collection は参照設定をまったく必要としません — VBA に組み込ま れています)です。New できない のは、Excel 自身のモデルオブジェクトです。New WorksheetNew Workbook もありません。これらはオブジェクトモデルを通じて作られます — Worksheets.AddWorkbooks.Add — Excel がその寿命を所有していて、あなたではないからです。Set ws = New Worksheet を試す と、実行時ではなくコンパイルエラーになります。

ExcelMaster の活用

オブジェクトを作る作業には、見た目以上に分かれ道があります。NewCreateObject か、事前バインディン グか遅延バインディングか、チェックする参照設定は要るか要らないか、そして解放と Is Nothing を静かに壊す Dim As New の近道。

ExcelMaster は、あなたの説明から正しいも のを選びます — マクロを他人のマシンで動かさなければならないと言えば CreateObject の遅延バインディング を、速度とツール支援が欲しいと言えば New の事前バインディングと参照設定のメモを選びます — そしてつねに Dim d As DictionarySet d = New Dictionary を分けるので、遅延生成と自己復活にかまれることはありま せん。ブックとコードはあなたの手元に残ります。

よくある質問

VBA の New は何をするのですか?

New は、クラスやライブラリの設計図からオブジェクトの真新しいインスタンスを作ります。Set d = New Dictionary は、まっさらで空の Dictionary をメモリ上に作り、d をそこへ向けます。新しいオブジェクトが 欲しいときは New を、すでに存在するオブジェクトを参照したいときは(New なしの)素の Set を使いましょう。

New と CreateObject のどちらを使うべきですか?

手元で管理するマシンで動き、IntelliSense・コンパイルチェック・速度が欲しいコードには New(事前バインデ ィング)を使います — Tools ▸ References でライブラリにチェックが要ります。配布するコードには CreateObject(遅延バインディング)を使います。参照設定が要らず、バージョ ンをまたいで可搬だからです。代償は IntelliSense がないことです。

Dim As New の何が問題なのですか?

Dim d As New Dictionary は、オブジェクトを最初の使用時に遅延生成し、アクセスのたびに隠れた Nothing チ ェックを差し込み、If d Is Nothing を事実上つねに False にし、Set d = Nothing のあとに次へ触れると 新しいオブジェクトをよみがえらせます。生成と解放を明示するために、Dim d As Dictionary に続けて Set d = New Dictionary とするほうが得策です。

Worksheet や Range に New は使えますか?

いいえ。Excel が WorksheetWorkbookRange などのモデルオブジェクトの寿命を所有しているので、 New Worksheet はありません。代わりにオブジェクトモデルを通じて作ります — Worksheets.AddWorkbooks.Add — そして New は、自作のクラスモジュールと DictionaryCollection のような生成可能な ライブラリのクラスにだけ使いましょう。

New に Set は必要ですか?

はい、オブジェクト変数には必要です。Set d = New DictionaryNew がオブジェクトを作り、Set が変数を そこへ向けます。Set を省く唯一の書き方は Dim d As New Dictionary ですが、これは前述の理由から避ける ことをおすすめします。

検証環境

動作確認: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-09-19.

関連ガイド: VBA Set · VBA Nothing · VBA CreateObject · VBA Dim · VBA Collection