Developer

【ExcelVBA】プロシージャの引数2(値渡しと参照渡し)
2021.06.20
Lv1

【ExcelVBA】プロシージャの引数2(値渡しと参照渡し)

プロシージャの引数2(値渡しと参照渡し)

引数を使ってプロシージャにデータを渡す方法は、大きく分けて「値渡し」と「参照渡し」の2種類があります。
前回紹介したのは、「参照渡し」です。今回は2つの方法を比較しながら違いについて紹介していきます。

値渡し

まずは、「値渡し」のサンプルプログラムを見てみましょう。
前回までと大きくことなるのは、「testByVal」プロシージャの引数の前に「ByVal」キーワードが付いているところです。
このキーワードを引数の前に付けることで、「値渡し」になります。

'' 値渡しのサンプル
Sub VBA基礎第22回_1()
    Dim buf As Integer
    
    buf = 1
    Call testByVal(buf)
    
    Debug.Print buf
    
End Sub
 
Sub testByVal(ByVal x As Integer)
 
    x = x + 10
     
End Sub

実行結果はイミディエイトウィンドウに「1」と表示されます。

処理の流れを見ていきましょう。
まず、呼び出し元で変数「buf」に「1」が代入されます。(プログラム5行目)

次に「testByVal」プロシージャが呼び出されます。このとき、引数に「buf」を指定していますので、変数「x」に「10」が代入されてプロシージャを実行します。(プログラム6行目)

呼び出されたプロシージャ側で変数「x」の値をプラス10します。(プログラム14行目)

プロシージャの処理が全て完了したので、呼び出し元に戻ります。

呼び出し元で変数「buf」を出力します。
変数「buf」の値は変わっていないため、最初に代入した「1」がイミディエイトウィンドウに表示されます。(プログラム8行目)

参照渡し

次に「参照渡し」のプログラムを見てみましょう。プロシージャ名を変更していますが、注目していただきたいのは、キーワードが「ByRef」に変わったところです。

'' 参照渡しのサンプル
Sub VBA基礎第22回_2()
    Dim buf As Integer
    
    buf = 1
    Call testByRef(buf)
    
    Debug.Print buf
    
End Sub

Sub testByRef(ByRef x As Integer)
 
    y = y + 10
     
End Sub

実行結果はイミディエイトウィンドウに「11」と表示されます。「値渡し」のときと実行結果が変わっていますね。

処理の流れを見ていきましょう。
まず、呼び出し元で変数「buf」に「1」が代入されます。(プログラム5行目)
※ここは「値渡し」と同じです。

次に「testByRef」プロシージャが呼び出されます。このとき、引数に「buf」を指定しています。(プログラム6行目)
※ここは「値渡し」と同じです。ここから先が変わります。
ただし、この変数「x」は呼び出し元の変数「buf」と実質的に同じ箱となります。そのため、変数「x」には変数「buf」と同じ値である「1」が保存されているように見えます。実際には同じ箱になるので変数名が異なるだけで、同じ変数と考えることもできます。
1つの箱(変数)にラベルが2つ付いている(「buf」と「x」)と考えて頂いてもOKです。

呼び出されたプロシージャ側で変数「x」の値をプラス10します。(プログラム14行目)
※ここは「値渡し」と同じです。ここから先が変わります。
「参照渡し」では、変数「buf」と変数「x」は同じものなので、変数「buf」の値もプラス10されたように見えます。
実際には、同じ箱(変数)のため、変数「x」と変数「buf」の値がそれぞれプラスされたと考えるのは誤りです。

プロシージャの処理が全て完了したので、呼び出し元に戻ります。
※ここは「値渡し」と同じです。

呼び出し元で変数「buf」を出力します。
変数「buf」の値はプロシージャの中でプラス10されているため、「11」がイミディエイトウィンドウに表示されます。(プログラム8行目)

最後に、引数の前に「ByRef」も「ByVal」もどちらも指定しなかった場合には、「ByRef」が指定されたものとみなされます。

まとめ

引数を使ってプロシージャにデータを渡す方法は、大きく分けて「値渡し」と「参照渡し」の2種類がある。
引数の定義をするときに、「値渡し」であれば「ByVal」を、「参照渡し」であれば「ByRef」を指定する。
どちらも指定していない場合には参照渡しである「ByRef」が指定されたものとみなされる。

確認問題

以下の「○○○」に当てはまる文言を解答してください。

引数の定義をするときに、「値渡し」であれば「○○○」を、「参照渡し」であれば「○○○」を指定する。
どちらも指定していない場合には参照渡しである「○○○」が指定されたものとみなされる。
「○○○」では、プロシージャ内で引数の値を変更したときに、その呼び出し元でもその変更が反映する。

答え

引数の定義をするときに、「値渡し」であれば「ByVal」を、「参照渡し」であれば「ByRef」を指定する。
どちらも指定していない場合には参照渡しである「ByRef」が指定されたものとみなされる。
参照渡し」では、プロシージャ内で引数の値を変更したときに、その呼び出し元でもその変更が反映する。

次回は、プロシージャの引数3です。

 
 

連載目次リンク

ExcelVBA 入門 連載目次