Excel VBA | ByRef を使うと危険なケース(初心者がハマりやすい罠集)

VBA
スポンサーリンク

VBA初心者が「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 UpdateAll()
    Dim msg As String
    msg = "Hello"
    AppendWorld msg
    AppendExclamation msg
    Debug.Print msg   ' → "Hello World!!!"
End Sub
VB
  • 解説: 呼び出し先がどんどん書き換えるため、「元の値がどこで変わったか」追えなくなる

3. 配列の構造変更(ReDim/Erase)

  • 罠: ByRef で渡した配列を ReDimErase すると、呼び出し元の配列も消える。
  • 例:
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 を基本にする

7. 関数の戻り値と混同

  • 罠: ByRef で値を返す設計にすると、関数の戻り値と二重で返すことになり混乱。
  • 解説: 「戻り値は1つ、複数返したいなら ByRef」というルールを守らないとコードが読みにくくなる。

✅ 安全に使うための指針

  • 基本は ByVal:副作用を避ける。
  • ByRef は「複数値を返したいとき」や「参照を意図的に差し替えたいとき」だけ。
  • オブジェクトや配列は特に注意:中身の変更と参照の付け替えを区別する。
  • 必ずコメントで意図を明示:「この引数は呼び出し元を書き換える」と書いておくと安心。

VBA
スポンサーリンク
シェアする
@lifehackerをフォローする
スポンサーリンク
タイトルとURLをコピーしました