ByVal と ByRef Macユーザー向け Excel VBA 入門 [08] Excel2019 for Mac

[08] ByVal と ByRef 、プロシージャ記述のオプション指定により結果が異なる場合(2つの例)
ByVal と ByRef 、文字列操作 と 数値操作 サンプル
・文字列操作 のサンプル
・数値操作 のサンプル
・デフォルト ByRef のため、状況に応じて ByVal (値渡し) キーワードを付加!
(注) 引数(パラメーター)指定した変数に「呼び出し先プロシージャの結果」を反映させたい場合のみ、 ByRef (参照渡し・ポインタ渡し) 指定を用います。
Macユーザー向け Excel VBA 入門 [08] ByVal と ByRef
まず、Excel メニューバーの [ヘルプ] - [更新プログラムのチェック] にて、適用されていないアップデートがあれば行ってください。
以下4つの操作方法がよく解らない方は、 Excel VBA 入門 [06] を参照して下さい。
(1) 「空のブック」Excelファイルを新規作成にて作成後、「名前を付けて保存…」にて、「Excel マクロ有効ブック(.xlsm)」ファイル形式を選び 任意の名前で保存。
(2) ( [マクロの記録] ボタンをクリックして)マクロの保存先に「作業中のブック」を指定後 [OK] ボタンをクリックし、「マクロの記録」を開始。 マクロ名は "Sample1" にて!
(3) 例えば「A3」セルを選択後、( [記録終了] ボタンをクリックして)「マクロの記録」を終了。
(4) [マクロ] ボタンをクリックして 先ほど作成した "Sample1" マクロを選択後 [編集] ボタンをクリックし、 VBEウィンドウ を開く。
![vba2019_primer[08] 04_png](https://1.bp.blogspot.com/-dwVUf2yTV5I/YRZc8tZAVaI/AAAAAAAABlk/R4DfkbeeaTMfPQ7tqe7CslpBv2pxbOe6QCLcBGAsYHQ/s0/20210813_04.png)
ByVal と ByRef 、プロシージャ記述のオプション指定により結果が異なる場合
' =========================================
Sub Sample1()
Dim buf As String ' 文字列型の変数を宣言
buf = "ABCDE" ' 変数に、文字列”ABCDE”を格納
Call Proc1(buf) ' プロシージャProc1の引数に変数を渡して呼出
MsgBox "Sample1: " & buf ' 変数の値を表示
End Sub
Sub Proc1(str As String) ' 省略すると、ByRef(参照渡し・ポインタ渡し)
str = str & "XYZ" ' 受け取った文字列に”XYZ”を加える
MsgBox "Proc1: " & str ' 変数の値を表示
End Sub
' =========================================
Sub Sample2()
Dim buf As String ' 文字列型の変数を宣言
buf = "ABCDE" ' 変数に、文字列”ABCDE”を格納
Call Proc2(buf) ' プロシージャProc2の引数に変数を渡して呼出
MsgBox "Sample2: " & buf ' 変数の値を表示
End Sub
Sub Proc2(ByVal str As String) ' 値渡し(変数のコピーが渡される)
str = str & "XYZ" ' 受け取った文字列に”XYZ”を加える
MsgBox "Proc2: " & str ' 変数の値を表示
End Sub
[VBE ウィンドウ]-[コード ウィンドウ]内の Sub Sample1() 以下を「上記のVBEコード」で置換します。
![vba2019_primer[08] 05_png](https://1.bp.blogspot.com/-PY8djX9-16A/YRZlnJ0q89I/AAAAAAAABls/zxEji_buG-AOVbj1cF-KGy23y1cgcSjyACLcBGAsYHQ/s0/20210813_05.png)
コピペ あるいは 入力 ミスチェックのため、以下画面のように VBAProject のコンパイル を行い 「VBAコードの文法チェック」が可能です。
![vba2019_primer[08] 06_png](https://1.bp.blogspot.com/-_twCbaavkL0/YRZmH98mJZI/AAAAAAAABl0/6ArsjS3e_7YTkY4IfJKaKkx2pvJlbQcPgCLcBGAsYHQ/s0/20210813_06.png)
ByVal と ByRef 、文字列操作 のサンプル
「イミディエイト ウィンドウ」にて call sample1() [return] と入力し Sample1() プロシージャを実行すると、以下2つのメッセージボックス画面を表示。
![vba2019_primer[08] 08_png](https://1.bp.blogspot.com/-yDujWwDfl8c/YRZpUJpT5wI/AAAAAAAABl8/NfYAKVClwvAARrrZcbblFi-n3Ul3uHXBQCLcBGAsYHQ/s0/20210813_08.png)
![vba2019_primer[08] 09_png](https://1.bp.blogspot.com/-5hOZXAmy8do/YRZprlzwH1I/AAAAAAAABmE/eujH4mxIc6gH2vUni-Et0JakQJYYlSpZgCLcBGAsYHQ/s0/20210813_09.png)
キーワードを省略した場合も ByRef (参照渡し)となり、Proc1() の引数(パラメーター)に指定した変数の変更を確認!
「イミディエイト ウィンドウ」にて call sample2() [return] と入力し Sample2() プロシージャを実行すると、以下2つのメッセージボックス画面を表示。
![vba2019_primer[08] 10_png](https://1.bp.blogspot.com/-M_MQ6Io9aUw/YRZrtfoJdGI/AAAAAAAABmM/16MYPFkH35Av38dZ9dQmynGGq1ekZe3cwCLcBGAsYHQ/s0/20210813_10.png)
![vba2019_primer[08] 11_png](https://1.bp.blogspot.com/-wglYSsmYo4Y/YRZWbdM9DDI/AAAAAAAABlc/zZLyokbrE3sFeHAii19OHyKWMR0QnpdPgCLcBGAsYHQ/s0/20210813_11.png)
ByVal キーワードを付加した場合、Proc2() の引数(パラメーター)には 指定した変数のコピー が与えられるため、 Sample2() 内の変数は変更されず元のまま 。
ByVal と ByRef 、数値操作 のサンプル
' =========================================
Sub Sample3()
Dim num As Integer ' 整数型の変数を宣言
num = 0 ' 変数に、 0 をセット
Call Proc3(num) ' プロシージャProc3の引数に変数を渡して呼出
MsgBox "Sample3: " & num ' 変数の値を表示
End Sub
Sub Proc3(num As Integer) ' 省略すると、ByRef(参照渡し・ポインタ渡し)
num = num + 1 ' 変数をインクリメント(+1する)
MsgBox "Proc3: " & num ' 変数の値を表示
End Sub
' =========================================
Sub Sample4()
Dim num As Integer ' 整数型の変数を宣言
num = 0 ' 変数に、 0 をセット
Call Proc4(num) ' プロシージャProc4の引数に変数を渡して呼出
MsgBox "Sample4: " & num ' 変数の値を表示
End Sub
Sub Proc4(ByVal num As Integer) ' 値渡し(変数のコピーが渡される)
num = num + 1 ' 変数をインクリメント(+1する)
MsgBox "Proc4: " & num ' 変数の値を表示
End Sub
[VBE ウィンドウ]-[コード ウィンドウ]内にて、 Sub Proc2 〜 End Sub 直後に「上記のVBEコード」を付け加えます。
コピペ あるいは 入力 ミスチェックのため、先程のように VBAProject のコンパイル を行い 「VBAコードの文法チェック」が可能です。
「イミディエイト ウィンドウ」にて call sample3() [return] と入力し Sample3() プロシージャを実行すると、以下2つのメッセージボックス画面を表示。
![vba2019_primer[08] 12_png](https://1.bp.blogspot.com/-iWYMw1u-nPs/YRZ2N4I4zNI/AAAAAAAABmU/wrLtHTM07yoRp7d78I0zK5T5XqXyUM8jACLcBGAsYHQ/s0/20210813_12.png)
![vba2019_primer[08] 13_png](https://1.bp.blogspot.com/-tIUU_6FQYf8/YRZ2dRvGEQI/AAAAAAAABmY/FFWgBd7YRWEN8NnjMRVHy1zj4-1PLWo8ACLcBGAsYHQ/s0/20210813_13.png)
キーワードを省略した場合も ByRef (参照渡し)となり、Proc3() の引数(パラメーター)に指定した変数の変更を確認!
「イミディエイト ウィンドウ」にて call sample4() [return] と入力し Sample4() プロシージャを実行すると、以下2つのメッセージボックス画面を表示。
![vba2019_primer[08] 14_png](https://1.bp.blogspot.com/-806rhrA6yZk/YRZ2xxMTopI/AAAAAAAABmk/Vk6YohKa_xwLBMyr_1Q8OXMgDBHFn0f6gCLcBGAsYHQ/s0/20210813_14.png)
![vba2019_primer[08] 15_png](https://1.bp.blogspot.com/-z4NX9ZGSbPc/YRZ2_gKlY9I/AAAAAAAABmo/NPPmsh247zkSQ8X1p4Mkw6KvcsWwSPYXQCLcBGAsYHQ/s0/20210813_15.png)
ByVal キーワードを付加した場合、Proc4() の引数(パラメーター)には 指定した変数のコピー が与えられるため、 Sample4() 内の変数は変更されず元のまま 。
デフォルト ByRef のため、状況に応じて ByVal (値渡し) キーワードを付加!
キーワードを省略した場合 ByRef (参照渡し・ポインタ渡し) となるため、状況に応じて ByVal (値渡し) キーワードを付加する必要があります。
ほとんどのプログラム言語では「値渡し」がデフォルト(省略値)ですが、なぜか Visual Basic 6.0 と VBA は「参照渡し」がデフォルトになっています。
「値渡し」をデフォルトにする理由は関数やプロシージャを一種のブラックボックスと考え、呼び出し元の変数が 呼び出し先にて勝手に変更されないようにするためです。
(不具合の発生を減らす努力を続ける事で)将来的にバグ回避に繋がりますので...
事実、最新の Visual Basic である VB.NET ( Visual Basic .NET ) では、 C# 等の他言語との互換性のため「値渡し」がデフォルトに変更されました。
結論として VBA では できる限り ByVal キーワードを付加して 呼び出し元の変数が勝手に変更されないようにし、敢えて 呼び出し元の変数に 呼び出し先プロシージャの結果を反映させたい場合のみ ByRef (参照渡し・ポインタ渡し)を用いるべき です。
なお、Function プロシージャの結果として返される変数は一つだけですが、プロシージャの引数(パラメーター)は複数指定できるので、ByRef を用いて 複数の結果を返すことも可能です。
Function プロシージャの結果として返される変数に、 配列や ユーザー定義型(構造体) を指定するほうが一般的ですが…
配列や ユーザー定義型(構造体) の説明は、また後日させて頂きます。
[command] + [Q] にてまず VBE を終了し、Excel のウィンドウ内を選択して [command] + [Q] にて Excel も終了させます。 「作業中のブック」を保存するか確認のダイアログ画面が表示された場合は 「保存」しましょう。 「自動保存」済みの場合、保存するかどうかの確認ダイアログ画面は表示されません。
次回は、 作成した ユーザー定義関数 を他のブックから呼び出す方法 を説明します。
最後まで読んでいただき、ありがとうございます。 また、お越しくださいませ。
// アタル