TL;DR —
Dim 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が、無言のタイプミスバグを、大声で知らせるコンパイルエラーに変える理由aをLongではなく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
i・j・k がすべて Long になると考えるのは、もっともなことです。しかし、
そうはなりません。Long なのは k だけです。 i と j は — それぞれに
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 が必要
値 — 数値、テキスト、日付 — を保持する変数は、= で代入します。オブジェクト
— Worksheet、Range、Workbook — を保持する変数は、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 のオブジェクトモデルの何か(Worksheet、Range、
Chart、Workbook)を指すなら、それには Set が必要です。
Dim を書く場所が、スコープと寿命を決める
Dim を書く場所は、飾りではありません — 誰が変数を見られるか、どれだけ
生き延びるかを決めます:
SubまたはFunctionの内側 → 変数はローカルです。手続きが始まると 生まれ、終わると消えます。外からは何も見えません。- モジュールの一番上、最初の手続きより前 → そのモジュール内のすべての
手続きから見えます。モジュール内に閉じ込めるには、そこで
Privateを使います。 - モジュールの一番上で
Public→ グローバルになり、プロジェクト全体から 見えます。強力ですが、乱用しやすいものです。どこからでも何にでも変更できる値は、 動きを追うのが難しくなります。
原則として、変数はできるだけローカルに宣言しましょう — それを使う手続きの
すぐ内側に。値が本当に共有されなければならないときだけ、モジュールレベルや
Public に手を伸ばします。スコープは、それ自体で 1 つのテーマです。手続きの
間で値を渡すなら、引数の流れを VBA Sub と
VBA ByRef vs ByVal で確認してください。
ExcelMaster の活用
Dim、Option 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 だけです。a は Variant です。As 句は、それが
直接くっついている変数だけに適用されるからです。両方を Long にするには
Dim a As Long, b As Long と書き、各変数に自分の As Type を与えます。
Option Explicit とは何で、どこに置きますか?
Option Explicit は、すべての変数を使う前に宣言することを強制します。すべての
モジュールの最初の行、あらゆる手続きより上に置きます。無言の「宣言されていない
タイプミス」バグを、明快な「変数が定義されていません」というコンパイルエラーに
変えます。**[ツール]→[オプション]→[編集]→「変数の宣言を強制する」**を
有効にすると、新しいモジュールに自動で追加されます。
Dim の代入で、= の代わりに Set を使うのはいつですか?
変数が Excel のオブジェクトモデルのオブジェクト — Worksheet、Range、
Workbook、Chart など — を保持するときに 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
