ByRef は「呼び出し元の変数を直接書き換える」ため便利ですが、初心者が使うと副作用で混乱しやすいです。そこで 安全に使うための設計パターン をコード例付きで整理します。
1. 複数値返却パターン
目的
関数の戻り値は1つしか返せないため、複数の結果を返したいときに ByRef を使う。
コード例
Sub GetCoordinates(ByRef x As Double, ByRef y As Double)
x = 10
y = 20
End Sub
Sub TestCoordinates()
Dim a As Double, b As Double
GetCoordinates a, b
Debug.Print a, b ' → 10, 20
End Sub
VBポイント
- 戻り値では1つしか返せない → 複数値返却に ByRef が便利。
- 引数名を「返却用」と分かるようにする(例:
ByRef resultX)。
2. 参照差し替えパターン
目的
呼び出し元の変数が指すオブジェクトや範囲を、意図的に別のものへ差し替える。
コード例
Sub MoveRange(ByRef r As Range)
Set r = r.Offset(1, 0) ' 呼び出し元も次の行を指すようになる
End Sub
Sub TestMoveRange()
Dim rng As Range
Set rng = Sheet1.Range("A1")
MoveRange rng
rng.Value = "Shifted" ' A2 に書き込まれる
End Sub
VBポイント
- 「参照を差し替える」意図を明示する。
- コメント必須:「このSubは参照を変更します」。
3. 戻り値+ByRefの役割分担
目的
- 主結果は戻り値で返す
- 副次結果は ByRef で返す
コード例
Function Divide(ByVal a As Double, ByVal b As Double, ByRef remainder As Double) As Double
remainder = a Mod b
Divide = a \ b
End Function
Sub TestDivide()
Dim q As Double, r As Double
q = Divide(10, 3, r)
Debug.Print q ' → 3
Debug.Print r ' → 1
End Sub
VBポイント
- 主結果は戻り値 → 読みやすい。
- 副次結果は ByRef → 複数返却が必要な場合に限定。
4. ByRef を「返却専用」にする
目的
入力は壊さず、出力専用の引数だけ ByRef にする。
コード例
Sub CalculateStats(ByVal arr() As Double, ByRef avg As Double, ByRef maxVal As Double)
Dim i As Long, sum As Double
sum = 0
maxVal = arr(LBound(arr))
For i = LBound(arr) To UBound(arr)
sum = sum + arr(i)
If arr(i) > maxVal Then maxVal = arr(i)
Next
avg = sum / (UBound(arr) - LBound(arr) + 1)
End Sub
Sub TestStats()
Dim data(1 To 3) As Double
Dim avg As Double, maxVal As Double
data(1) = 10: data(2) = 20: data(3) = 30
CalculateStats data, avg, maxVal
Debug.Print avg, maxVal ' → 20, 30
End Sub
VBポイント
- 入力は必ず ByVal。
- 出力専用の引数だけ ByRef。
- 役割を分けることで副作用を防ぐ。
5. 参照破棄を明示的に行う
目的
呼び出し元の参照を意図的に消す(リソース解放)。
コード例
Sub ReleaseRange(ByRef r As Range)
Set r = Nothing ' 呼び出し元も参照が消える
End Sub
Sub TestRelease()
Dim rng As Range
Set rng = Sheet1.Range("A1")
ReleaseRange rng
Debug.Print rng Is Nothing ' → True
End Sub
VBポイント
- 「このSubを呼ぶと参照が消える」とコメントで明示。
- 誤用すると Null 参照エラーになるため注意。
✅ 総まとめ
- 基本は ByVal → 副作用を避ける。
- ByRef は「返却用」「参照差し替え用」に限定。
- 戻り値と ByRef を使い分ける → 主結果は戻り値、副次結果は ByRef。
- コメントや名前付けで意図を明示 → 読みやすく安全。


