VBA技術解説
値渡し(ByVal)、参照渡し(ByRef)について

ExcelマクロVBAの問題点と解決策、VBAの技術的解説
最終更新日:2020-04-10

値渡し(ByVal)、参照渡し(ByRef)について


ByValが値渡し、ByRefが参照渡しです。
ここまでは、どこにでも書いてあります。
しかし、なんとなく理解できるけど、なんとなく理解できない・・・


結局のところ実際の活用がなかなか出来ない事が多いようです。
使用例を通じて、理解して下さい。

ByVal(値渡し)とByRef(参照渡し)

ByVal:値渡し

変数の中のデータを渡すもので、呼出側の変数は影響を受けません。
つまり、値渡しでは、呼び出し先で引数の値を変更しても、呼び出し元の引数は変更されません。

VBA マクロ 値渡し ByVal 参照渡し ByRef

変数の値を求めて、その値を渡します。
呼び出し先から戻ってきて、変数の値は変化しません。

ByRef:参照渡し

変数そのものを渡すもので、呼出側の変数が影響を受けます。
つまり、参照渡しでは、呼び出し先で引数の値を変更すると、呼び出し元の引数も変更されます。

VBA マクロ 値渡し ByVal 参照渡し ByRef

変数そのものを渡します。
呼び出し先で引数の値を変更した場合は、その変更後の引数が呼び出し元の変数に入ります。

ただし、呼び出し元で変数ではなく、関数や数式を引数にした場合や、変数を括弧()で囲んだ場合は値渡し(ByVal)になります。
以下の記述は、呼び出し先がByRef(参照渡し)てもByVal(値渡し)になります。
本来は必要のない括弧()を付けている場合
Call 呼び出し先((変数))
呼び出し先 (変数)
変数を評価して値を求めてから、その値を渡すことになります。
VBAでの括弧()の使い方、括弧が必要な場合
オブジェクトのメソッドや、プロシージャー(Sub、Function)を呼ぶときに、引数を括弧()で囲うのか、囲わないのか… 初心者が赤い文法エラーが出て悩むことの一つです。VBAでは、どんな時に括弧を付けて、どんな時に括弧を付けないのか… ・括弧が必要な場合 ・括弧が不要な場合 これらについて具体的な例とともに解説します。

関数や数式の場合
Call 呼び出し先(関数(変数))
Call 呼び出し先(変数+変数)
関数や数式なので、そのままでは渡すことはできないので、値評価後に値を渡します。

普通の変数(プリミティブ型)の場合



Sub sample1()
  Dim i, j
  i = 1
  j = 1
  Call sub1(i, j)
  MsgBox i
  MsgBox j
End Sub
Sub sub1(arg1, arg2)
  arg1 = arg1 + 1
  arg2 = arg2 + 2
End Sub

上記のsample1を実行すると、2,3の順にメッセージ表示されます。
ByValもByRef指定していないので、省略時のByRefとなっています。
この場合、ByRefなので参照渡しとなり、Call元のプロシージャーの引数も変更されます。

Sub sample2()
  Dim i, j
  i = 1
  j = 1
  Call sub2(i, j)
  MsgBox i
  MsgBox j
End Sub
Sub sub2(ByVal arg1, ByVal arg2)
  arg1 = arg1 + 1
  arg2 = arg2 + 2
End Sub

上記のsample2を実行すると、1,1の順にメッセージ表示されます。
ByValを指定しているので値渡しとなっています。
この場合、Call元のプロシージャーの引数は変更されません。

普通の変数(プリミティブ型)は理解しやすいと思います。

オブジェクト変数の場合

オブジェクト変数については、以下を参照してください。
オブジェクト変数とは何か|VBA技術解説
VBAを使い始めてからある程度進むとオブジェクト変数を必ず使い始めることになります。しかし、オブジェクト変数をどうやって使ったらよいのか、オブジェクト変数とはどういうものなのか… ここの理解で苦しんでいることが多々あるようです。VBA入門は現在137回までありますが、オブジェクト変数については第52回.オブジェクト変数とSetステートメントででてきます。

引数にオブジェクトを指定した場合に、勘違いしている場合が多いです。



Sub sample()
  Dim MyRange As Range
  Set MyRange = Range("A1")
  Call sample2(MyRange)
End Sub

Sub sample2(ByVal MyRange As Range)
  MyRange.Value = 1
End Sub

上記の結果は、A1セルに1が入ります。
当然ですよね。
つまり、ByValで渡されたオブジェクトに変更を加えれば、呼出元でもオブジェクトは変更されています。

Range以外の他のオブジェクトでも同じことです。
では、オブジェクトの場合、ByValとByRefの違いは何でしょうか?

オブジェクト変数がByValの場合

Sub sample()
  Dim MyRange As Range
  Set MyRange = Range("A1")
  Call sample2(MyRange)
  MyRange.Value = 2
End Sub

Sub sample2(ByVal MyRange As Range)
  MyRange.Value = 1
  Set MyRange = Range("A2")
End Sub

上記の結果は、A1セルに2が入るだけです。
sample2での
Set MyRange = Range("A2")
これは、ByValなので呼出元に影響を与えません。

オブジェクト変数がByRefの場合

Sub sample()
  Dim MyRange As Range
  Set MyRange = Range("A1")
  Call sample2(MyRange)
  MyRange.Value = 2
End Sub

Sub sample2(ByRef MyRange As Range)
  MyRange.Value = 1
  Set MyRange = Range("A2")
End Sub

この結果は、A1セルに1、A2セルに2が入ります。
sample2での
Set MyRange = Range("A2")
この変更が、呼出元に返されています。

ここでは、とても単純な例にしましたが、
オブジェクトを引数に使う場合の参考にして下さい。



同じテーマ「マクロVBA技術解説」の記事

WorksheetFunctionについて
RangeとCellsの深遠
Offset、Resizeを使いこなそう
値渡し(ByVal)、参照渡し(ByRef)について
最終行・最終列の取得方法(End,CurrentRegion,SpecialCells,UsedRange)
ユーザー定義関数の作り方
セルの値について(Value,Value2,Text)
Excelのバージョンを判断して「名前を付けて保存」
空白セルを正しく判定する方法(IsEmpty,IsError,HasFormula)
空白セルを正しく判定する方法2
Rangeオブジェクト.Valueの省略について


新着記事NEW ・・・新着記事一覧を見る

VBA100本ノック 37本目:グラフの色設定|VBA練習問題(12月1日)
VBA100本ノック 36本目:列の並べ替え|VBA練習問題(12月1日)
VBA100本ノック 35本目:条件付き書式|VBA練習問題(11月29日)
VBA100本ノック 34本目:配列の左右回転|VBA練習問題(11月28日)
VBA100本ノック 33本目:マクロ記録の改修|VBA練習問題(11月26日)
VBA100本ノック 32本目:Excel終了とテキストファイル出力|VBA練習問題(11月25日)
VBA100本ノック 31本目:入力規則|VBA練習問題(11月24日)
将棋とプログラミングについて~そこには型がある~|エクセル雑感(11月22日)
VBA100本ノック 30本目:名札作成(段組み)|VBA練習問題(11月22日)
VBA100本ノック 29本目:画像の挿入|VBA練習問題(11月21日)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
5.マクロって何?VBAって何?|VBA入門
6.繰り返し処理(For Next)|VBA入門
7.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
8.セルに文字を入れるとは(Range,Value)|VBA入門
9.とにかく書いてみよう(Sub,End Sub)|VBA入門
10.マクロはどこに書くの(VBEの起動)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ