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

Excel VBA の Dim — 変数の宣言、Option Explicit、そしてタイプミスが生む「空の箱」

|

Excel VBA の Dim — 変数の宣言、Option Explicit、そしてタイプミスが生む「空の箱」

TL;DRDim name As Type は名前付きの箱を確保し、使う前にその形を 決めます:Dim total As Long。VBA では宣言は任意です — そして、それこそが 問題なのです。宣言しなければ、変数名をたった 1 つ打ち間違えるだけで、それが 無言で真新しい空の Variant になり、合計は 0 のまま、エラーは一切 出ません。すべてのモジュールの一番上に Option Explicit を置きましょう。 これはすべての変数の宣言を強制するので、タイプミスは間違った答えではなく、 コンパイルエラー(「変数が定義されていません」)になります。この言語で最も レバレッジの高い 1 行です。

Option Explicit          ' <- すべてのモジュールの一番上に置く

Sub Demo()
    Dim total As Long    ' "total" という名前の整数用の箱を確保する
    Dim name As String   ' "name" という名前のテキスト用の箱を確保する

    total = 10 + 5
    name = "Invoice"
    Debug.Print name, total   ' -> Invoice      15
End Sub

どのマクロも、扱う対象に名前を付けることから始まります — 行カウンター、 ワークシート、集計中の合計、といった具合に。それをやるのが Dim です。事務 書類のように見えますが、これを飛ばしたり(あるいはいい加減にやったり)する ことは、エラーを一切出さない一群のバグの原因になります — 最悪の種類の バグです。マクロは最後まで走り切り、自信たっぷりに間違った数値を返してくる からです。

この記事で学べること

  • Dim が実際に何をしているのか — 名前付きの箱を確保し、さらにその形を決めること
  • Option Explicit が、無言のタイプミスバグを、大声で知らせるコンパイルエラーに変える理由
  • aLong ではなく Variant にしてしまう Dim a, b As Long の罠
  • ただの = では足りず、Set が必要になる場面(オブジェクト)
  • 変数をどこで宣言するかが、誰から見えるか・どれだけ生きるかを決めること

考え方の軸:Dim は、中身を入れる前にラベル付きの箱を確保する

変数を、メモリ上のラベル付きの箱だと考えてください。Dim total As Long は 2 つのことを同時に行います。箱を確保して total というラベルを貼ること、 そしてその箱の形を Long(整数)に固定することです。以降、total = 15 は その箱に値を入れ、total という名前はそれを読み戻します。

このラベルは、初心者が思う以上に重要です。VBA が、見覚えのない名前に出くわした ときにどう振る舞うかが理由です。既定では — Option Explicit がなければ — VBA が 知らない名前に対して示す反応は「エラー」ではありません。「おや、新しい変数だ」 であり、それをこっそり、空のまま作ってくれるのです。このたった 1 つの設計判断が、 VBA で最も混乱を招くバグの源であり、次のセクションがその対策です。

最悪の VBA バグから救うルール:Option Explicit

バグそのものを 3 行で示します:

Sub AddThemUp()
    total = 0
    total = totl + 10      ' タイプミス:"total" ではなく "totl"
    Debug.Print total      ' -> いつまでも 10 — タイプミスが新しい空の箱を作った
End Sub

あなたは total のつもりで totl と打ちました。Option Explicit がなければ、 VBA はそれを指摘しません。totl という真新しい空の Variant(値は 0 / Empty)を勝手に作り、何もない値に 10 を足し、本物の total は決して積み 上がりません。赤い文字も、メッセージボックスもなし — ただ、レポートに載るまで 気づかないかもしれない間違った結果があるだけです。

Option Explicit は、この種のバグを丸ごと終わらせます。モジュールの最初の 行に置くと、宣言が必須になります。すべての変数は、使う前に Dim(または Private / Public)に現れなければなりません。こうなればタイプミスは幽霊の 箱を作れません — 宣言されていない名前なので、VBA はコンパイル時に止まります:

Option Explicit

Sub AddThemUp()
    Dim total As Long
    total = 0
    total = totl + 10      ' コンパイルエラー:変数が定義されていません("totl" が強調表示される)
End Sub

エラーは、マクロが走り出す前に、打ち間違いをまっすぐ指し示します。既定でどこ でも有効にしましょう:**[ツール]→[オプション]→[編集]→「変数の宣言を 強制する」**にチェックを入れると、新しいモジュールすべてに Option Explicit が自動で追加されます(既存のモジュールには手で足す必要があります)。「変数が 定義されていません」は贈り物だと思いましょう — たった今、バグを無料で捕まえて くれたのです。

各 Dim を 1 つの型に結びつけるルール:Dim a, b As Long の罠

これは、ほぼ誰もが一度はやる宣言のミスです。Long のカウンターが 3 つ欲しくて、 こう書きます:

Dim i, j, k As Long

ijk がすべて Long になると考えるのは、もっともなことです。しかし、 そうはなりません。Long なのは k だけです。 ij は — それぞれに As 句がないので — Variant です。VBA では、型はそれが直接くっついている 変数だけに適用されます。「型をリスト全体に広げる」ようなルールはありません。

' 誤り — i と j は Variant で、Long なのは k だけ
Dim i, j, k As Long

' 正しい — すべての変数が自分の型を持つ
Dim i As Long, j As Long, k As Long

' 最も明快 — 1 行に 1 つ
Dim i As Long
Dim j As Long
Dim k As Long

この失敗は厄介です。コードは動いてしまうからです。Variant は数値を問題なく 保持できます。あなたは、手に入れたつもりだった型安全性と速度を失い、バグは 後になって初めて表面化します — 「Long」のはずの変数の 1 つが、本来受け付けるべき でないテキストや巨大な値を無言で受け入れたときに。すべての変数に、自分の As Type を与えましょう。

オブジェクトのためのルール:ただの = では足りず、Set が必要

— 数値、テキスト、日付 — を保持する変数は、= で代入します。オブジェクトWorksheetRangeWorkbook — を保持する変数は、Set で代入 しなければなりません。Set を忘れることは、もう 1 つの典型的な初心者の ミスです。

Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Data")   ' オブジェクトには Set が必須
Debug.Print ws.Range("A1").Value

Dim rng As Range
Set rng = ws.Range("A1:A10")               ' ここでも Set

Set を省くと、VBA はオブジェクトを代入しません — 代わりにそのオブジェクトの 既定値を読もうとし、**「オブジェクト変数または With ブロック変数が設定されて いません (エラー 91)」「オブジェクトが必要です (エラー 424)」**が出ます。 このルールは機械的で、覚える価値があります:値型は =、オブジェクト型は Set 型名が Excel のオブジェクトモデルの何か(WorksheetRangeChartWorkbook)を指すなら、それには Set が必要です。

Dim を書く場所が、スコープと寿命を決める

Dim を書く場所は、飾りではありません — 誰が変数を見られるか、どれだけ 生き延びるかを決めます:

  • Sub または Function の内側 → 変数はローカルです。手続きが始まると 生まれ、終わると消えます。外からは何も見えません。
  • モジュールの一番上、最初の手続きより前 → そのモジュール内のすべての 手続きから見えます。モジュール内に閉じ込めるには、そこで Private を使います。
  • モジュールの一番上で Publicグローバルになり、プロジェクト全体から 見えます。強力ですが、乱用しやすいものです。どこからでも何にでも変更できる値は、 動きを追うのが難しくなります。

原則として、変数はできるだけローカルに宣言しましょう — それを使う手続きの すぐ内側に。値が本当に共有されなければならないときだけ、モジュールレベルや Public に手を伸ばします。スコープは、それ自体で 1 つのテーマです。手続きの 間で値を渡すなら、引数の流れを VBA SubVBA ByRef vs ByVal で確認してください。

ExcelMaster の活用

DimOption Explicit、そして規律あるスコープ設計は、1 年分の編集を生き 延びるマクロと、腐っていくマクロとを分けるものです。同時に、それらは摩擦でも あります — 本当に気にかけている部分にたどり着く前に書く、几帳面な宣言の 数々です。

ExcelMaster を 使えば、結果へと一足飛びに進めます。タスクを平易な日本語で説明するだけ — 「Orders シートで、ステータスが Paid の行について D 列を合計して、月ごとに まとめて」といった具合に — すれば、Option Explicit を覚えておく手間をあなたに 残す代わりに、正しい変数と型を堅牢なやり方で宣言しながら、そのロジックを書いて 実行してくれます。それでも、定期実行する手書きのマクロが必要なときは、 これからも自分で Dim を書くことになるでしょう。しかし「今日のデータでとにかく これを片付けたい」という日々の作業なら、結果を説明する方が、宣言を一つひとつ 手で正しく書くより勝るのです。

よくある質問

VBA で変数を宣言しなければなりませんか?

技術的にはいいえ — VBA は、宣言していない変数を Variant として扱い、使わせて くれます。しかし実務では、すべてを宣言すべきです。宣言していない変数は、 たった 1 つのタイプミスに、無言で新しい空の箱を作らせ、エラーなしで間違った 答えを生ませるからです。すべてのモジュールの一番上に Option Explicit を置いて、 宣言を必須にしましょう。

VBA の Dim とは何ですか?

Dim は "dimension"(次元)の略です — 初期の BASIC で配列の次元を確保して いたことに由来します。今日では単に「変数を宣言する」ことを意味します:メモリ上に 名前付きの場所を確保し、As Type でどんな種類の値を保持するかを固定します。 例:Dim count As Long

Dim a, b As Long は a と b の両方を Long にしますか?

いいえ。Long なのは b だけです。aVariant です。As 句は、それが 直接くっついている変数だけに適用されるからです。両方を Long にするには Dim a As Long, b As Long と書き、各変数に自分の As Type を与えます。

Option Explicit とは何で、どこに置きますか?

Option Explicit は、すべての変数を使う前に宣言することを強制します。すべての モジュールの最初の行、あらゆる手続きより上に置きます。無言の「宣言されていない タイプミス」バグを、明快な「変数が定義されていません」というコンパイルエラーに 変えます。**[ツール]→[オプション]→[編集]→「変数の宣言を強制する」**を 有効にすると、新しいモジュールに自動で追加されます。

Dim の代入で、= の代わりに Set を使うのはいつですか?

変数が Excel のオブジェクトモデルのオブジェクトWorksheetRangeWorkbookChart など — を保持するときに Set を使います: Set ws = ActiveSheet — 数値、テキスト、日付、Boolean — にはただの = を使います。オブジェクトで Set を忘れると「オブジェクト変数または With ブロック変数が設定されていません (エラー 91)」が出ます。

検証環境

検証環境: Excel 365(Windows 11)、VBA 7.1 — 最終確認 2026-07-31。

関連ガイド: VBA Data Types · VBA Const · VBA Sub · VBA ByRef vs ByVal · VBA Range