About
このページで学習出来る事
前回は関数の[Sub]と[Function]の違いについて説明しましたが、今回は関数への値の渡し方について説明をします。
値の渡し方には[ByVal(値渡し)]と[ByRef(参照渡し)]の二種類が存在し、それぞれ違った動きをしますので、変数の動きに気を付けながら見ていきたいと思います。
サンプルコード
[sample-07.xlsm]を開いて、中に書かれているコードを確認しましょう。
今回のコードでは、二種類の関数[subByValAction]と[subByRefAction]が書かれています。それぞれ変数の値がどう変化をしていくか見ていきます。
このファイルをそのまま使用しても構いませんし、新しくエクセルファイルを作って、自身でコードを記載して動かしても構いません。(直接コードを書いた方が覚えやすいので、時間がある方は書く練習もしてみましょう)
Sub main()
Dim tempNum As Integer
tempNum = 10
Call subByValAction(tempNum)
Debug.Print (tempNum)
Call subByRefAction(tempNum)
Debug.Print (tempNum)
End Sub
Private Sub subByValAction(ByVal tempNum As Integer)
tempNum = 50
Debug.Print (tempNum)
End Sub
Private Sub subByRefAction(ByRef tempNum As Integer)
tempNum = 50
Debug.Print (tempNum)
End Sub
コードの解説 sub main()部分
‘引数に[tempNum]を設定し[subByValAction]関数を呼び出しています。
‘呼び出したい関数の前に[Call]を付けることで、関数が呼び出せます。
Call subByValAction(tempNum)
‘引数に[tempNum]を設定し[subByRefAction]関数を呼び出しています。
Call subByRefAction(tempNum)
コードの解説 Sub subByValAction()部分
‘変数の前に[ByVal]を指定し、値渡しで変数を受け取れるよう設定しています。
Private Sub subByValAction(ByVal tempNum As Integer)
コードの解説 Sub subByRefAction()部分
‘変数の前に[ByRef]を指定し、参照渡しで変数を受け取れるよう設定しています。
Private Sub subByRefAction(ByRef tempNum As Integer)
[ByVal(値渡し)]での処理確認
[ByVal(値渡し)]とは変数の値を関数へ渡すという意味で、イメージとしては[コピー&ペースト]に近いです。
変数の値をコピーして関数に渡す。そんなイメージです。
実際の動きを確認するために、[Debug.Print]の所でブレークポイントを設定して実行してみましょう。
[subByValAction]関数の中にあるブレークポイントで止まったところで、ローカルウィンドウにある[tempNum]を確認すると、「10」という値を渡された[tempNum]が「50」となっているのが確認できます。
Sub関数(ByVal)からの戻り値について
変数の確認が終わったら、ブレークポイントで止まっている状態から再度動かしてみましょう。
次のブレークポイントで止まったら再度[tempNum]を確認すると、先ほど「50」であった数値が「10」に戻っていると思います。
これは[subByValAction]関数の処理結果が[sub main()]に反映されていないために起こる現象です。
どうして処理した結果が反映されないのかと言うと、前回も説明した通り「[Sub]で定義される関数は値を返さない」という特徴を持つ関数だからです。
[ByRef(参照渡し)]での処理確認
次に[ByRef(参照渡し)]ですが、これは変数の値を関数へ渡すのではなく、変数の場所を参照させるという意味で、イメージとしては[ショートカットやリンク]に近いです。
エクセルファイルのショートカットをメールで送るイメージです。ファイル自体を送っているのではなく、ファイルの場所を送っている感じです。
それでは、ブレークポイントで止まっている状態から再度動かしてみましょう。今度は[subByRefAction]関数の中にあるブレークポイントで止まったところで確認出来ます。
これは処理が関数[subByRefAction]に移ったことを意味します。
続けてローカルウィンドウにある[tempNum]を確認すると「50」という数値が入っている事が確認できます。
Sub関数(ByRef)からの戻り値について
次に参照渡しでの値の変化を確認するために、再度ブレークポイントで止まっている状態から動かしてみましょう。
次のブレークポイントで止まった後に[tempNum]を確認すると、先ほどと同様に「50」の数値になっていると思います。
これは[ByVal(値渡し)]と違い、[ByRef(参照渡し)]の特徴により起こる現象です。
先ほども説明しましたが、[ByRef(参照渡し)]はファイルのショートカットのようなイメージです。ショートカットで開いたファイルを上書き保存すると、元ファイルが更新されるのと同じ動きが、この[ByRef(参照渡し)]でも起きているのです。
この場合、[tempNum]という変数を参照していますので、その参照先にて値を変更したら、参照元の[tempNum]も同様に値が変更されている事になります。
最後に([ByVal(値渡し)]と[ByRef(参照渡し)]の使い分け)
今回は関数へ値を渡す、二種類の方法について説明をしました。
では、具体的にどのような場面で、[ByVal(値渡し)]と[ByRef(参照渡し)]を使い分ければ良いかというと、次の場面で[ByRef(参照渡し)]を使用し、それ以外は[ByVal(値渡し)]を使えば大きな問題にはなりません。
[ByRef(参照渡し)]を使用する場面
・再帰処理で処理内容を追っていく場合、トータルカウントを保持したい場合
・連続して複数の関数処理が行われる場合(メソッドチェーンなど)
・変数の値が大きい場合
・配列を渡す場合
[ByRef(参照渡し)]を多用すると、どこのタイミングで値が変わるかを追うのが難しくなってきます。
上記の様な限られた場面で使用するか、ポリシーを持って使用するように心がけてください。
次回は、関数の[Private]と[Public]の違いについて説明したいと思います。
このページで学習出来る事 前回まではブックやシートオブジェクトの操作に関して解説をしてきましたが、6回目となる今回は、VBAの関数操作に関して説明をしていきます。 一般的にコードは書けば書くほど行数が長くなっていきますが、プロ[…]
このページで学習出来る事 前回は関数の[ByVal(値渡し)]と[ByRef(参照渡し)]の違いについて説明しましたが、今回は関数の呼び出し方や[Private]と[Public]の違いについて説明していきます。 関数には[Privat[…]