練習問題と解答解説
では「値渡し(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 両方で書いてみると違いがよく分かります。例えば「割引計算」「文字列整形」「セル更新」など。
