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

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

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


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


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


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

ByVal:値渡し

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

マクロ VBA サンプル画像

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


ByRef:参照渡し

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

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

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

ただし、呼出元で変数ではなく、関数や数式を引数にした場合や、変数を括弧()で囲んだ場合は値渡し(ByVal)になります。
以下の記述は、呼出し先がByRef(参照渡し)でもByVal(値渡し)になります。
本来は必要のない括弧()を付けている場合
Call 呼び出し先((変数))
呼び出し先 (変数)
変数を評価して値を求めてから、その値を渡すことになります。
VBAでの括弧()の使い方、括弧が必要な場合
・基本文型 ・VBAにおける括弧() ・VBAにおける半角空白の意味 ・戻り値を他の用途に使う時 ・括弧()の使い方の基本文型 ・Callを省略しなければ全て括弧が必要になる ・最後に一言

関数や数式の場合
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技術解説
・そもそも変数とは何か ・変数の入れ物としての大きさは ・オブジェクト変数にオブジェクトは入っていない ・オブジェクト変数のメモリアドレス ・Is演算子によるオブジェクトの比較 ・TypeOf演算子 ・オブジェクト変数を使う時の注意点 ・オブジェクト変数の最後に

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



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")
この変更が、呼出し元に返されています。

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


サイト内のByVal,ByRefの記事

Variant仮引数のByRefとByValの挙動違い
ツイッターで出したVBAのお題です。Variant型は、どんなデータ型も入れることができてしまいます。具体的なデータ型の代わりに使用することで、より柔軟にVBA記述ができるようになります。ただしこの便利さゆえに、逆に注意しなければならない挙動もあります。
オブジェクトのByRef、ByVal、Variant
ツイッターで出題した問題です。オブジェクトを引数にした場合の、ByRef、ByValの違いと、仮引数にVariantを指定した場合の動作違いを問う問題です。出題ツイート 【VBA問題】 Submain() Range("A1")=1 DimaAsRange:Seta=Range("A1…




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

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


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

数字(1~50)を丸付き数字に変換するVBA|VBA技術解説(2022-11-15)
TEXTAFTER関数(テキストの指定文字列より後ろの部分を返す)|エクセル入門(2022-11-14)
TEXTBEFORE関数(テキストの指定文字列より前の部分を返す)|エクセル入門(2022-11-14)
TEXTSPLIT関数(列と行の区切り記号で文字列を分割)|エクセル入門(2022-11-12)
LAMBDA以降の新関数はVBAで使えるか|VBA技術解説(2022-11-11)
WRAPCOLS関数(1次元配列を指定数の列で折り返す)|エクセル入門(2022-11-08)
WRAPROWS関数(1次元配列を指定数の行で折り返す)|エクセル入門(2022-11-08)
EXPAND関数(配列を指定された行と列に拡張する)|エクセル入門(2022-11-07)
TAKE関数(配列の先頭/末尾から指定行/列数を取得)|エクセル入門(2022-11-06)
DROP関数(配列の先頭/末尾から指定行/列数を除外)|エクセル入門(2022-11-06)


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

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.繰り返し処理(For Next)|VBA入門
5.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
6.Excelショートカットキー一覧|Excelリファレンス
7.並べ替え(Sort)|VBA入門
8.エクセルVBAでのシート指定方法|VBA技術解説
9.マクロって何?VBAって何?|VBA入門
10.ExcelマクロVBAの基礎を学習する方法|エクセルの神髄




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


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



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