Excel VBA | 参照渡し(ByRef)

VBA
スポンサーリンク

練習問題と解答解説

では「値渡し(ByVal)」と「参照渡し(ByRef)」をテーマにした 練習問題10問 とその 解答・解説 をまとめます。初心者が「違いを体感」できるように、段階的に難易度を上げています。


1. 数値を渡す(ByVal)

問題: 変数 x=10 を ByVal で渡し、呼び出し先で x=x+5。呼び出し元の x はどうなる?

解答コード:

Sub Test1()
    Dim x As Integer
    x = 10
    AddFiveByVal x
    Debug.Print x   ' → 10
End Sub

Sub AddFiveByVal(ByVal n As Integer)
    n = n + 5
End Sub
VB

解説: ByVal はコピーを渡すので、呼び出し元の x は変わらない。


2. 数値を渡す(ByRef)

問題: 変数 x=10 を ByRef で渡し、呼び出し先で x=x+5。呼び出し元の x は?

解答コード:

Sub Test2()
    Dim x As Integer
    x = 10
    AddFiveByRef x
    Debug.Print x   ' → 15
End Sub

Sub AddFiveByRef(ByRef n As Integer)
    n = n + 5
End Sub
VB

解説: ByRef は本体を渡すので、呼び出し元の x が書き換わる。


3. 文字列を渡す(ByVal)

問題: 文字列 msg="Hello" を ByVal で渡し、呼び出し先で " World" を追加。呼び出し元は?

解答コード:

Sub Test3()
    Dim msg As String
    msg = "Hello"
    AppendWorldByVal msg
    Debug.Print msg   ' → "Hello"
End Sub

Sub AppendWorldByVal(ByVal s As String)
    s = s & " World"
End Sub
VB

解説: ByVal なので呼び出し元は変わらない。


4. 文字列を渡す(ByRef)

問題: 文字列 msg="Hello" を ByRef で渡し、呼び出し先で " World" を追加。呼び出し元は?

解答コード:

Sub Test4()
    Dim msg As String
    msg = "Hello"
    AppendWorldByRef msg
    Debug.Print msg   ' → "Hello World"
End Sub

Sub AppendWorldByRef(ByRef s As String)
    s = s & " World"
End Sub
VB

解説: ByRef なので呼び出し元の変数が書き換わる。


5. 複数の値を返す

問題: Sub に ByRef 引数を2つ渡し、1つ目に「こんにちは」、2つ目に「こんばんは」を代入。

解答コード:

Sub Test5()
    Dim a As String, b As String
    SetGreeting a, b
    Debug.Print a   ' → "こんにちは"
    Debug.Print b   ' → "こんばんは"
End Sub

Sub SetGreeting(ByRef x As String, ByRef y As String)
    x = "こんにちは"
    y = "こんばんは"
End Sub
VB

解説: 複数の値を返したいときは ByRef が便利。


6. 関数で安全に返す

問題: 金額 1000 に消費税10%を加えた値を返す関数を作り、元の値は変えない。

解答コード:

Sub Test6()
    Dim price As Double
    price = 1000
    Debug.Print AddTax(price)   ' → 1100
    Debug.Print price           ' → 1000
End Sub

Function AddTax(ByVal amount As Double) As Double
    AddTax = amount * 1.1
End Function
VB

解説: ByVal+戻り値で「副作用なし」に設計できる。


7. デフォルトの挙動

問題: 引数に ByVal/ByRef を書かない場合、どちらになる?

解答コード:

Sub Test7()
    Dim x As Integer
    x = 5
    AddFiveDefault x
    Debug.Print x   ' → 10
End Sub

Sub AddFiveDefault(n As Integer)
    n = n + 5
End Sub
VB

解説: VBAではデフォルトが ByRef。意図せず書き換わるので注意。


8. 配列を渡す

問題: 配列を ByRef で渡し、要素を書き換える。

解答コード:

Sub Test8()
    Dim arr(1 To 3) As Integer
    arr(1) = 10
    ChangeArray arr
    Debug.Print arr(1)   ' → 99
End Sub

Sub ChangeArray(ByRef a() As Integer)
    a(1) = 99
End Sub
VB

解説: 配列は ByRef で渡すと中身が直接変更される。


9. ByValで配列を渡す

問題: 配列を ByVal で渡すとどうなる?

解答コード:

Sub Test9()
    Dim arr(1 To 3) As Integer
    arr(1) = 10
    TryChangeArray arr
    Debug.Print arr(1)   ' → 10
End Sub

Sub TryChangeArray(ByVal a() As Integer)
    a(1) = 99
End Sub
VB

解説: ByVal で配列を渡すと「参照のコピー」が渡されるため、要素変更は呼び出し元に影響しない。


10. 実践:セルの値を更新

問題: セルA1の値を ByRef で渡し、呼び出し先で「!!!」を追加。

解答コード:

Sub Test10()
    Dim txt As String
    txt = Range("A1").Value
    AddExclamation txt
    Range("A1").Value = txt
End Sub

Sub AddExclamation(ByRef s As String)
    s = s & "!!!"
End Sub
VB

解説: ByRef で渡すことで、呼び出し先で加工した結果をそのままセルに反映できる。


✅ 総まとめ

  • ByVal: コピーを渡す → 呼び出し元は変わらない。安全。
  • ByRef: 本体を渡す → 呼び出し元も変わる。複数値返却に便利。
  • デフォルトはByRef → 意図せず書き換わるので注意。
  • 基本はByVal+戻り値、安全設計。必要なときだけByRef。

👉 さらに理解を深めたいなら「自分の作りたい処理」を ByVal と ByRef 両方で書いてみると違いがよく分かります。例えば「割引計算」「文字列整形」「セル更新」など。

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