参照渡し「ByRef」と値渡し「ByVal」の違い(Excel VBA)

先日、指定したフォルダ内のサブフォルダのフォルダ名を全部取得(Excel VBA)で出てきました

Call プロシージャ名(引数
↓↓↓↓
Sub プロシージャ名(引数

の流れ、難しくないですか?

Callで引数を受け取って、その引数をプロシージャの中で使用することができるのですが、引数の渡し方には2通りあります。
参照渡し「ByRef」値渡し「ByVal」です。

参照渡し「ByRef」

下記コードを実行すると・・・

Sub 参照渡しByRefをする場合()
    Dim 変数A As String
    変数A = "参照渡し変数だよ。"
    MsgBox "メッセージ1:" & 変数A '「メッセージ1:参照渡し変数だよ。」と表示される
    Call 参照渡しを受け取るよ(変数A)
    MsgBox "メッセージ4:" & 変数A '「メッセージ4:参照を変更したよ。」と表示される
End Sub

Sub 参照渡しを受け取るよ(ByRef 変数A As String)
    '「参照渡しByRefをする場合」プロシージャから
    '変数A="参照渡し変数だよ。"を引数として受け取り実行
    MsgBox "メッセージ2:" & 変数A '「メッセージ2:参照渡し変数だよ。」と表示される
    変数A = "参照を変更したよ。"
    MsgBox "メッセージ3:" & 変数A '「メッセージ3:参照を変更したよ。」と表示される
   
    '変数A=”参照を変更したよ。"と変数を変更した状態で
    '「参照渡しByRefをする場合」プロシージャに戻る
End Sub

こんな感じでメッセージが表示されます。

   変数A = “参照渡し変数だよ。”
↓↓↓↓↓↓↓↓↓↓↓↓
   変数A = “参照渡し変数だよ。”
↓↓↓↓↓↓↓↓↓↓↓↓
   変数A = “参照を変更したよ。”
↓↓↓↓↓↓↓↓↓↓↓↓
   変数A = “参照を変更したよ。”

「参照渡しByRefをする場合」プロシージャでは、

変数A = “参照渡し変数だよ。”

と引数が渡されます。そしてその引数は「参照渡しを受け取るよ」プロシージャに引き渡されて、そのまま使用することができます。

そして「参照渡しを受け取るよ」プロシージャで

変数A = “参照を変更したよ。”

と変更されてから、「参照渡しByRefをする場合」プロシージャに戻る時、変数A = “参照を変更したよ。”を

変更した状態のまま、元のプロシージャに戻ります

それが参照渡し「ByRef」の効果です。

処理開始時の値を受け取り、処理終了時の値を元のプロシージャに返します。

指定したフォルダ内のサブフォルダのフォルダ名を全部取得(Excel VBA)では、こちらの参照渡しを利用していました。

では

Call フォルダ名一覧取得(pt, ws, t_row)
↓↓↓
Sub フォルダ名一覧取得(pt As String, ws As Worksheet, t_row As Long)

としていたのですが、なぜ

Sub フォルダ名一覧取得(ByRef pt As String, ByRef ws As Worksheet, ByRef t_row As Long)

という風に「ByRef」を付けていなかったのでしょうか?

それは「ByRef」は省略してもよいことになっているので、省略していたのです。

引数の前には「ByRef」か「ByVal」のどちらかが付くことになりますが、何も付いていなかったら「ByRef」参照渡しだなぁ~と覚えておきましょう。

■■■スポンサーリンク■■■

値渡し「ByVal」

下記コードを実行すると・・・

Sub 値渡しByValをする場合()
    Dim 変数B As String
    変数B = "値渡し変数だよ。"
    MsgBox "メッセージ1:" & 変数B '「メッセージ1:値渡し変数だよ。」と表示される
    Call 値渡しを受け取るよ(変数B)
    MsgBox "メッセージ4:" & 変数B '「メッセージ4:値渡し変数だよ。」と表示される
End Sub

Sub 値渡しを受け取るよ(ByVal 変数B As String)
    '「値渡しByValをする場合」プロシージャから
    '変数B="値渡し変数だよ。"を引数として受け取り実行
    MsgBox "メッセージ2:" & 変数B '「メッセージ2:値渡し変数だよ。」と表示される
    変数B = "参照を変更したよ。"
    MsgBox "メッセージ3:" & 変数B '「メッセージ3:参照を変更したよ。」と表示される
    '変数B=”参照を変更したよ。"という変更は
    '「値渡しByValをする場合」プロシージャには返さない
End Sub

こんな感じでメッセージが表示されます。

   変数B = “値渡し変数だよ。”
↓↓↓↓↓↓↓↓↓↓↓↓
   変数B = “値渡し変数だよ。”
↓↓↓↓↓↓↓↓↓↓↓↓
   変数B = “参照を変更したよ。”
↓↓↓↓↓↓↓↓↓↓↓↓
   変数B = “値渡し変数だよ。”

「値渡しByValをする場合」プロシージャでは、

変数B =”値渡し変数だよ。”

と引数が渡されます。そしてその引数は「値渡しを受け取るよ」プロシージャに引き渡されて、使用することができます。

「値渡しを受け取るよ」プロシージャで

変数B = “参照を変更したよ。”

と変更されてから、「値渡しByValをする場合」プロシージャに戻る時、変数A = “参照を変更したよ。”という変更は

引き継がれず、元のプロシージャに戻ります

それが値渡し「ByVal」の効果です。

処理開始時の値は受け取りますが、処理終了時の値は元のプロシージャに戻しません。

以上、参照渡し「ByRef」と値渡し「ByVal」の違いでした。

【参考】

指定したフォルダ内のファイル名全てを取得(Excel VBA)
変数でよく使われる「buf」「tmp」の意味
Dir関数が取得するファイルの順番
指定したフォルダ内のフォルダ名全てをGetAttrを使って「エラー53 ファイルが見つかりません。」を出さずに取得(Excel VBA)
GetAttrとは?「= vbDirectory」ではなく「And vbDirectory」となるビット演算の疑問
フォルダ名だけを取得したい時に出てくる 「.」 と 「..」 とは?
指定したフォルダ内とサブフォルダ内全てのファイル名を取得(Excel VBA)
CreateObject(“Scripting.FileSystemObject”) を使ってサブフォルダを取得
再帰処理とは?フォルダ内とサブフォルダ内全てのファイル名を取得(Excel VBA)
指定したフォルダ内のサブフォルダのフォルダ名を全部取得(Excel VBA)
再帰処理とは?フォルダ内のサブフォルダのフォルダ名を全部取得(Excel VBA)
参照渡し「ByRef」と値渡し「ByVal」の違い(Excel VBA)
ファイルのフルパスからファイル名のみを取得 InStrRev関数(Excel VBA)
指定したフォルダの全ての階層のフォルダ名・サブフォルダ名・ファイル名を取得(Excel VBA)
FileSystemObjectとは?CreateObject 関数 FolderExists・GetFolderの使い方
FileSystemObject CreateObject関数を使う方法・ 参照設定を使う方法 違いを理解してエラー防止
再帰処理とは?指定したフォルダの全ての階層のフォルダ名・サブフォルダ名・ファイル名を取得(Excel VBA)
ファイルのフルパスからファイル名のみを取得 Split関数(Excel VBA)
Callステートメントとは 引数 括弧()の使い方(Excel VBA)
指定したフォルダ内から「特定の文字を含まないファイル名」を取得(Excel VBA)
ワイルドカードとは。使い方いろいろ。(Excel)
Dir関数の使い方。ファイル名やフォルダ名の取得方法。(Excel VBA)
指定したフォルダのファイル名を取得し、そのファイル名を一括で変換(Excel VBA)
Excel起動時に「コンパイルエラー」。64ビット システムで Declareステートメントに、PtrSafe属性を設定(Excel VBA )
「ファイルを開く」ダイアログボックス から ファイル名を取得(Excel VBA)
「ファイルを開く」ダイアログボックス から 複数 ファイル名を取得(Excel VBA)
指定フォルダ内のサブフォルダ全てをフォルダ構成のみ(空フォルダ)を別フォルダにコピー(Excel VBA)
再帰処理とは?指定フォルダ内のサブフォルダ全てをフォルダ構成のみ(空フォルダ)を別フォルダにコピー(Excel VBA)

■■■スポンサーリンク■■■