VBA初心者が ByRef(参照渡し) を使うときに陥りやすい罠を整理しました。ByRefは便利ですが、呼び出し元の変数が直接書き換わるため、意図しない副作用が起きやすいです。
1. デフォルトが ByRef 問題
- 罠: 引数に何も指定しないと自動的に ByRef になる。
- 例:
Sub AddFive(n As Integer) ' ← ByRef 扱い
n = n + 5
End Sub
Sub Test()
Dim x As Integer
x = 10
AddFive x
Debug.Print x ' → 15(意図せず書き換わる)
End Sub
VB- 解説: 「戻り値を返すつもりがないのに変数が変わる」ことが混乱の原因。
→ 必ず ByVal を明示する習慣をつける。
2. 複数のプロシージャで値が壊れる
- 罠: 同じ変数を複数のSubに渡すと、どこで書き換えられたか分からなくなる。
- 例:
Sub UpdateAll()
Dim msg As String
msg = "Hello"
AppendWorld msg
AppendExclamation msg
Debug.Print msg ' → "Hello World!!!"
End Sub
VB- 解説: 呼び出し先が次々に書き換えるため、「元の値がどこで変わったか」追えなくなる。
3. 配列の構造変更(ReDim/Erase)
- 罠: ByRefで渡した配列を
ReDimやEraseすると、呼び出し元の配列も消える。 - 例:
Sub ClearArray(ByRef arr() As Long)
Erase arr
End Sub
VB- 解説: 呼び出し元の配列が突然消えるため、後続処理でエラーになる。
→ 配列の構造変更は戻り値で新しい配列を返す方が安全。
4. オブジェクト参照の付け替え
- 罠: RangeやWorksheetをByRefで渡して
Setし直すと、呼び出し元の参照も変わる。 - 例:
Sub MoveRange(ByRef r As Range)
Set r = r.Offset(1, 0)
End Sub
VB- 解説: 呼び出し元の変数が意図せず別セルを指すようになる。
→ 「中身を変える」処理と「参照を変える」処理を混同しやすい。
5. Nothing の代入で参照が消える
- 罠: ByRefで渡したオブジェクトに
Set obj = Nothingすると、呼び出し元の参照も消える。 - 例:
Sub KillRange(ByRef r As Range)
Set r = Nothing
End Sub
VB- 解説: 呼び出し元で
r.Valueを使おうとするとエラー。
→ 参照破棄は呼び出し元に影響するため危険。
6. デバッグ困難な副作用
- 罠: ByRefの副作用で「どこで値が変わったか」分からなくなる。
- 例: 複数モジュールで同じ変数を渡し回すと、値が予期せず変わる。
- 解説: デバッグ時に「どこで壊れたか」追跡が難しい。
→ 副作用を減らすために ByVal を基本にする。
✅ 安全に使うための指針
- 基本は ByVal。
- ByRef は「返却用」「参照差し替え用」に限定。
- コメントや名前付けで意図を明示(例:
ByRef resultX As Double)。 - 戻り値と ByRef を使い分ける → 主結果は戻り値、副次結果は ByRef。
- 参照破棄や差し替えは危険なので必ず明示的に設計。


