変数宣言とデータ型
VBA でプログラムを書く際、変数はデータを一時的に記憶しておくための「箱」のような役割を果たします。変数を正しく宣言し、適切なデータ型を選ぶことは、バグの少ない、効率的なコードを書くための第一歩です。
この記事では、変数宣言の基本から、各データ型の特徴と使い分け、変数のスコープ(有効範囲)、そして Option Explicit によるバグ防止まで、VBA の変数に関するすべてを詳しく解説します。
変数が必要となるシチュエーション
実務では、以下のような場面で変数が必要になります:
- 同じ値を繰り返し使用する: シート名やファイルパスなど、何度も参照する値を変数に格納して再利用する
- 計算結果を保持する: 途中の計算結果を保存して、後の処理で活用する
- 条件によって異なる値を扱う: If 文の結果に応じて変わる値を一時的に保持する
- ループのカウンター: For 文で繰り返し回数を管理する
- コードの可読性向上: マジックナンバーを避け、意味のある名前で値を管理する
変数宣言の基本
Dim ステートメント
VBA で変数を宣言するには Dim ステートメントを使用します。Dim は “Dimension”(次元・領域)の略で、変数のための領域を確保することを意味します。
Sub VariableDeclarationBasic()
' 変数を宣言する
Dim name As String
Dim age As Long
Dim price As Double
Dim isActive As Boolean
' 値を代入する
name = "山田太郎"
age = 30
price = 1980.5
isActive = True
' 値を使う
Debug.Print name ' => 山田太郎
Debug.Print age ' => 30
Debug.Print price ' => 1980.5
Debug.Print isActive ' => True
End Sub
VBA では、変数の宣言と初期化を同時に行うことはできません。Dim name As String = "山田" のような書き方はエラーになります。宣言と代入は必ず別の行で書いてください。
変数名のルール
VBA の変数名には以下のルールがあります:
- 先頭文字: 英字(アルファベット)で始める必要がある
- 使用可能文字: 英字、数字、アンダースコア(
_) - 使用不可文字: スペース、ピリオド、
!、@、&、$、#など - 予約語の禁止:
Sub、Dim、If、Stringなどの VBA 予約語は使えない - 文字数: 最大 255 文字
- 大文字・小文字: 区別されない(
myVarとMyVarは同じ変数)
' ○ 良い変数名
Dim userName As String
Dim totalAmount As Long
Dim rowIndex As Long
Dim isCompleted As Boolean
Dim filePath As String
' × 使えない変数名
' Dim 1stName As String ' 数字で始まっている
' Dim user name As String ' スペースが含まれている
' Dim Sub As String ' 予約語
VBA では一般的にローワーキャメルケース(先頭小文字、単語の区切りは大文字)が使われます。例: userName、totalCount、filePath。
ループカウンターには i、j、k を使うのが慣例です。
データ型一覧と選び方
VBA で使用できる主要なデータ型を、用途ごとに整理して紹介します。
数値型
| データ型 | 名称 | 範囲 | メモリ | 用途 |
|---|---|---|---|---|
Byte | バイト型 | 0 〜 255 | 1 byte | 小さい正の整数 |
Integer | 整数型 | -32,768 〜 32,767 | 2 byte | 小さい整数 |
Long | 長整数型 | -2,147,483,648 〜 2,147,483,647 | 4 byte | 一般的な整数(推奨) |
Single | 単精度浮動小数点数型 | ±1.4E-45 〜 ±3.4E+38 | 4 byte | 小数を含む数値 |
Double | 倍精度浮動小数点数型 | ±4.9E-324 〜 ±1.8E+308 | 8 byte | 高精度な小数(推奨) |
Currency | 通貨型 | -922,337,203,685,477.5808 〜 922,337,203,685,477.5807 | 8 byte | 金額計算(丸め誤差なし) |
その他の型
| データ型 | 名称 | 説明 | メモリ |
|---|---|---|---|
String | 文字列型 | テキストデータを格納 | 10 byte +α |
Boolean | ブール型 | True または False のみ | 2 byte |
Date | 日付型 | 日付と時刻を格納 | 8 byte |
Object | オブジェクト型 | オブジェクトへの参照 | 4 byte |
Variant | バリアント型 | あらゆるデータ型を格納(既定の型) | 16 byte +α |
Integer と Long の使い分け
VBA を始めたばかりの方は「整数なら Integer でいいのでは?」と思うかもしれません。しかし、実務では Long の使用を推奨します。
Sub IntegerVsLong()
Dim rowCount As Integer
Dim rowCountLong As Long
' Integer では Excel の行数を扱えない!
' Excel のシートは最大 1,048,576 行
' Integer の上限は 32,767 なのでオーバーフローエラーになる
' rowCount = Cells(Rows.Count, 1).End(xlUp).Row ' エラーの可能性あり
' Long なら安全に扱える
rowCountLong = Cells(Rows.Count, 1).End(xlUp).Row ' OK
Debug.Print "最終行: " & rowCountLong
End Sub
Integer 型は最大 32,767 までしか格納できません。Excel のシートは最大 1,048,576 行あるため、行番号を扱う変数に Integer を使用するとオーバーフローエラー(実行時エラー 6)が発生する可能性があります。特別な理由がない限り、整数には Long 型を使用してください。
String 型の使い方
文字列型には可変長と固定長の2種類があります。
Sub StringTypes()
' 可変長文字列(一般的)
Dim name As String
name = "山田太郎"
Debug.Print name ' => 山田太郎
Debug.Print Len(name) ' => 4
' 固定長文字列(特殊な用途向け)
Dim code As String * 5
code = "ABC"
Debug.Print code ' => "ABC "(5文字に満たない分はスペースで埋められる)
Debug.Print Len(code) ' => 5
' 文字列の結合
Dim fullName As String
Dim firstName As String
Dim lastName As String
firstName = "太郎"
lastName = "山田"
fullName = lastName & " " & firstName
Debug.Print fullName ' => 山田 太郎
End Sub
文字列の結合には & 演算子を使用します。+ 演算子でも結合できますが、数値型と混在するとエラーの原因になるため、文字列結合には常に & を使用するのが安全です。
Boolean 型
Boolean 型は True(真)または False(偽)の2つの値のみを取ります。条件の結果を保持する際に頻繁に使用します。
Sub BooleanUsage()
Dim isFound As Boolean
Dim isEmpty As Boolean
' 条件式の結果を代入
isFound = (Range("A1").Value = "検索対象")
isEmpty = (Range("B1").Value = "")
' 条件分岐に活用
If isFound Then
Debug.Print "見つかりました"
End If
' Boolean 型の初期値は False
Dim isActive As Boolean
Debug.Print isActive ' => False
End Sub
Variant 型 — 使うべきか避けるべきか
Variant 型はあらゆるデータ型の値を格納できる万能型です。データ型を指定せずに宣言した場合、自動的に Variant 型になります。
Sub VariantBehavior()
' 型を指定しないと Variant になる
Dim value1 ' Variant 型
Dim value2 As Variant ' 明示的に Variant を指定(同じ結果)
value1 = 100 ' 数値を代入
Debug.Print TypeName(value1) ' => Integer
value1 = "テスト" ' 文字列に変更可能
Debug.Print TypeName(value1) ' => String
value1 = #2025/01/01# ' 日付にも変更可能
Debug.Print TypeName(value1) ' => Date
End Sub
Sub VariantPitfall()
' 注意: Dim a, b, c As Long は a と b が Variant になる!
Dim a, b, c As Long
Debug.Print TypeName(a) ' => Empty(Variant)
Debug.Print TypeName(b) ' => Empty(Variant)
Debug.Print TypeName(c) ' => Long
' 正しい書き方
Dim x As Long, y As Long, z As Long
End Sub
Dim a, b, c As Long と書くと、Long 型になるのは c だけです。a と b は Variant 型になります。
複数の変数を同じ型で宣言する場合は、Dim a As Long, b As Long, c As Long のように各変数にデータ型を指定してください。これは VBA 初心者が最もつまずきやすいポイントの一つです。
Variant 型は便利ですが、以下の理由からできるだけ避けましょう:
- メモリ使用量が多い(16 byte 以上)
- 型の不一致によるバグが発見しにくい
- コードの意図が読み取りにくい
- パフォーマンスが低下する
ただし、ワークシートの値を一括で配列に取得する場合など、Variant が必要な場面もあります。
各データ型の初期値
変数を宣言しただけで値を代入していない場合、データ型ごとに以下の初期値が設定されます。
| データ型 | 初期値 |
|---|---|
Long | 0 |
Double | 0 |
String | ""(空文字列) |
Boolean | False |
Date | 0:00:00 |
Object | Nothing |
Variant | Empty |
Sub CheckDefaultValues()
Dim num As Long
Dim text As String
Dim flag As Boolean
Dim dt As Date
Debug.Print "Long: " & num ' => Long: 0
Debug.Print "String: " & text ' => String:
Debug.Print "Boolean: " & flag ' => Boolean: False
Debug.Print "Date: " & dt ' => Date: 0:00:00
End Sub
Option Explicit — 変数宣言の強制
Option Explicit とは
Option Explicit は、モジュールの先頭に記述することで、すべての変数の宣言を強制する命令です。未宣言の変数を使用するとコンパイルエラーが発生するようになります。
Option Explicit
Sub WithOptionExplicit()
Dim userName As String
userName = "山田太郎"
' スペルミスがあるとコンパイルエラーになる!
' Debug.Print userNmae ' => コンパイルエラー: 変数が定義されていません
Debug.Print userName ' => 山田太郎(正しい)
End Sub
Option Explicit がないとどうなるか
Option Explicit を記述しないと、VBA は未宣言の変数を自動的に Variant 型として作成します。これが思わぬバグの原因になります。
' Option Explicit が記述されていない場合
Sub WithoutOptionExplicit()
Dim totalAmount As Long
totalAmount = 1000
' スペルミスに気づかない!
' "totalAmout" という別の Variant 変数が暗黙的に作成される
Debug.Print totalAmout ' => ""(空の Variant が表示される)
' 計算結果がおかしくなる原因に
totalAmout = totalAmout + 500 ' totalAmount ではなく totalAmout に加算
Debug.Print totalAmount ' => 1000(期待値は 1500)
End Sub
Option Explicit を使用しないと、変数名のタイプミスがエラーにならず、発見困難なバグの原因になります。VBE の設定で自動挿入を有効にすることを強く推奨します。
Option Explicit の自動挿入設定
VBE(Visual Basic Editor)で、新規モジュール作成時に Option Explicit を自動的に挿入する設定ができます。
- VBE を開く(Excel で Alt + F11)
- メニューの「ツール」→「オプション」を選択
- 「編集」タブの「変数の宣言を強制する」にチェックを入れる
- 「OK」をクリック
この設定を一度行えば、以降作成するすべてのモジュールに Option Explicit が自動で挿入されます。VBA を始めたら最初に設定しておきましょう。
変数のスコープ(有効範囲)
VBA の変数には、どこからアクセスできるかを決めるスコープ(有効範囲)があります。スコープを正しく理解することで、意図しない変数の上書きやバグを防ぐことができます。
プロシージャレベル変数
Sub や Function の内部で Dim を使って宣言した変数は、そのプロシージャ内でのみ使用できます。プロシージャの実行が終了すると、変数の値は破棄されます。
Sub ProcedureA()
Dim message As String
message = "プロシージャA のメッセージ"
Debug.Print message ' => プロシージャA のメッセージ
End Sub
Sub ProcedureB()
' ProcedureA の message にはアクセスできない
' Debug.Print message ' => コンパイルエラー(Option Explicit 有効時)
Dim message As String
message = "プロシージャB のメッセージ"
Debug.Print message ' => プロシージャB のメッセージ
End Sub
モジュールレベル変数
モジュールの先頭(プロシージャの外側)で Dim または Private を使って宣言した変数は、同じモジュール内のすべてのプロシージャからアクセスできます。
Option Explicit
' モジュールレベル変数(このモジュール内でのみ有効)
Dim sheetName As String
Private counter As Long
Sub InitializeModule()
sheetName = "データ一覧"
counter = 0
End Sub
Sub IncrementCounter()
counter = counter + 1
Debug.Print sheetName & " - カウント: " & counter
End Sub
グローバル変数(Public 変数)
モジュールの先頭で Public を使って宣言した変数は、プロジェクト内のすべてのモジュールからアクセスできます。
' Module1 の先頭に記述
Public appTitle As String
Public maxRetryCount As Long
' Module2 から Module1 の Public 変数にアクセス
Sub UseGlobalVariable()
appTitle = "売上管理ツール"
maxRetryCount = 3
Debug.Print appTitle ' => 売上管理ツール
End Sub
スコープの比較
| 宣言方法 | 宣言場所 | 有効範囲 |
|---|---|---|
Dim | プロシージャ内 | そのプロシージャ内のみ |
Dim / Private | モジュールの先頭 | そのモジュール内のすべてのプロシージャ |
Public | モジュールの先頭 | プロジェクト全体 |
Static | プロシージャ内 | そのプロシージャ内(値は保持される) |
Static で宣言した変数は、プロシージャの実行が終了しても値が保持されます。プロシージャが呼び出されるたびにカウントアップしたい場合などに便利です。
Sub CountCalls()
Static callCount As Long
callCount = callCount + 1
Debug.Print "この関数は " & callCount & " 回呼び出されました"
End Sub
' 1回目の呼び出し => "この関数は 1 回呼び出されました"
' 2回目の呼び出し => "この関数は 2 回呼び出されました"
' 3回目の呼び出し => "この関数は 3 回呼び出されました"
Public 変数はどこからでもアクセスできて便利ですが、多用すると以下の問題が発生します:
- どこで値が変更されたか追跡しにくい
- プロシージャ間の依存関係が複雑になる
- テストやデバッグが困難になる
可能な限りプロシージャレベル変数を使用し、値の受け渡しは引数と戻り値で行いましょう。
オブジェクト変数と Set ステートメント
オブジェクト変数の宣言
ワークブック、ワークシート、Range などのオブジェクトを変数に格納する場合は、Set ステートメントを使用して代入します。
Sub ObjectVariables()
' オブジェクト変数の宣言と代入
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
Dim rng As Range
Set rng = ws.Range("A1:D10")
Dim wb As Workbook
Set wb = ThisWorkbook
' オブジェクト変数を使用する
Debug.Print ws.Name ' => Sheet1
Debug.Print rng.Address ' => $A$1:$D$10
Debug.Print wb.Name ' => ブック名
End Sub
オブジェクト変数への代入で Set を忘れると、実行時エラー 91「オブジェクト変数または With ブロック変数が設定されていません」が発生します。
Dim ws As Worksheet
ws = ThisWorkbook.Sheets("Sheet1") ' × エラー!
Set ws = ThisWorkbook.Sheets("Sheet1") ' ○ 正しい オブジェクト変数の解放
オブジェクト変数を使い終わったら Nothing を代入して解放するのがよい習慣です。
Sub ReleaseObject()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
' シートの操作を行う
ws.Range("A1").Value = "完了"
' オブジェクト参照を解放
Set ws = Nothing
End Sub
定数の宣言(Const)
プログラム実行中に変更されない値は、変数ではなく**定数(Const)**として宣言します。
Option Explicit
' モジュールレベルの定数
Private Const TAX_RATE As Double = 0.1
Private Const MAX_ROWS As Long = 1000
Public Const APP_NAME As String = "売上管理システム"
Sub CalculateTax()
Dim price As Long
price = 1000
Dim taxIncluded As Double
taxIncluded = price * (1 + TAX_RATE)
Debug.Print APP_NAME & ": 税込価格 = " & taxIncluded ' => 売上管理システム: 税込価格 = 1100
End Sub
定数名は大文字のスネークケース(TAX_RATE、MAX_RETRY_COUNT)で書くのが一般的です。これにより変数との区別が一目でつくようになります。
データ型の選び方ガイド
実務で変数を宣言する際の、データ型の選び方をまとめます。
用途別の推奨データ型
| 用途 | 推奨データ型 | 理由 |
|---|---|---|
| 行番号・列番号 | Long | Excel の最大行数(1,048,576)を超えない |
| ループカウンター | Long | Integer のオーバーフローを防止 |
| 金額計算 | Currency | 丸め誤差が発生しない |
| 小数を含む計算 | Double | Single より精度が高い |
| フラグ(はい/いいえ) | Boolean | True/False で明確に表現できる |
| テキスト処理 | String | 文字列専用 |
| 日付・時刻の処理 | Date | 日付計算に便利な関数が使える |
| シートの値を一括取得 | Variant | 配列として取得する際に必要 |
初心者向け選択フローチャート
迷ったらこのフローで選びましょう:
- 数値? → 整数なら
Long、小数ならDouble、お金ならCurrency - 文字列? →
String - はい/いいえ? →
Boolean - 日付? →
Date - オブジェクト? → 具体的なオブジェクト型(
Worksheet、Rangeなど) - よく分からない →
Variant(ただし後で適切な型に変更する)
実践的な活用例
例1:データの集計処理
Option Explicit
Sub AggregateData()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("売上データ")
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Dim totalSales As Currency
Dim itemCount As Long
Dim averageSales As Double
totalSales = 0
itemCount = 0
Dim i As Long
For i = 2 To lastRow ' 2行目から(1行目はヘッダー)
Dim amount As Currency
amount = ws.Cells(i, 3).Value ' 3列目が金額と仮定
totalSales = totalSales + amount
itemCount = itemCount + 1
Next i
' 平均を計算
If itemCount > 0 Then
averageSales = totalSales / itemCount
End If
Debug.Print "合計: " & FormatCurrency(totalSales)
Debug.Print "件数: " & itemCount
Debug.Print "平均: " & FormatCurrency(averageSales)
Set ws = Nothing
End Sub
例2:ファイルパスの組み立て
Option Explicit
Sub BuildFilePath()
Const BASE_FOLDER As String = "C:\Reports\"
Const FILE_PREFIX As String = "monthly_report_"
Const FILE_EXTENSION As String = ".xlsx"
Dim currentYear As Long
Dim currentMonth As Long
currentYear = Year(Date)
currentMonth = Month(Date)
' ファイル名を組み立てる
Dim fileName As String
fileName = FILE_PREFIX & currentYear & "_" & Format(currentMonth, "00") & FILE_EXTENSION
Dim fullPath As String
fullPath = BASE_FOLDER & fileName
Debug.Print fullPath ' => C:\Reports\monthly_report_2026_02.xlsx
End Sub
注意点とトラブルシューティング
よくあるエラーと対処法
| エラー | 原因 | 対処法 |
|---|---|---|
| 「型が一致しません」(エラー 13) | 変数の型と代入する値の型が合わない | データ型を確認し、型変換関数(CLng、CStr 等)を使う |
| 「オーバーフロー」(エラー 6) | 値がデータ型の範囲を超えた | Long や Double など、より大きい型を使用 |
| 「変数が定義されていません」 | Option Explicit 有効時に未宣言の変数を使用 | 変数を Dim で宣言する |
| 「オブジェクト変数が設定されていません」(エラー 91) | Set を使わずにオブジェクト変数に代入 | Set ステートメントを使用する |
型変換関数
異なるデータ型間で値を変換する場合は、型変換関数を使用します。
Sub TypeConversion()
Dim text As String
text = "12345"
' 文字列 → 数値
Dim num As Long
num = CLng(text) ' => 12345
' 数値 → 文字列
Dim numStr As String
numStr = CStr(num) ' => "12345"
' その他の型変換関数
' CInt() - Integer に変換
' CDbl() - Double に変換
' CCur() - Currency に変換
' CBool() - Boolean に変換
' CDate() - Date に変換
End Sub
練習問題
まとめ
- 変数は
Dim 変数名 As データ型で宣言し、代入は別の行で行う - 整数には
IntegerではなくLongを使用するのがベストプラクティス Dim a, b As LongではaはVariant型になる。各変数に型を指定するOption Explicitを必ず有効にして、未宣言変数によるバグを防止する- VBE のオプションで「変数の宣言を強制する」を有効にしておく
- 変数のスコープは必要最小限にする(プロシージャレベル > モジュールレベル > グローバル)
- オブジェクト変数の代入には
Setが必要 - 変更されない値は定数(
Const)として宣言する