Variant仮引数のByRefとByValの挙動違い
ツイッターで出したVBAのお題です。
Variant型は、どんなデータ型も入れることができてしまいます。
具体的なデータ型の代わりに使用することで、より柔軟にVBA記述ができるようになります。
ただしこの便利さゆえに、逆に注意しなければならない挙動もあります。
お題のツイート
Sub sample()
Dim rng1 As Range, rng2 As Range
Set rng1 = Range("A1:B1")
Set rng2 = Range("A2:B2")
Call sample_sub(rng1, rng2)
End Sub
Sub sample_sub(ByRef v1, ByVal v2)
v1 = 1
v2 = 1
MsgBox WorksheetFunction.Sum(v1, v2)
End Sub
sampleの実行結果は?
・1
・2
・3
・4

解説のツイート
ByRef、ByVal、呼ばれた関数ではどちらもRangeオブジェクトとして受け取ります。
しかし、このときByRefとByValでは一部挙動に違いが現れます。
受け取ったRangeオブジェクトに対するVBA記述によって違いが出てきます。
Set代入した場合には、
ByRefなら参照私として呼び出し元も変化しますが、
ByValなら受け取るだけであり呼び出し元は変化しません。
Range = 値
このLet代入でRangeが複数セルでも全てのセルのValueに値が入ります。
仮引数がRange型(As Range)であれば、Let代入は同じ動作となります。
しかしVariantでRangeを受け取った場合は、Let代入で挙動に違いが出てきます。
ByRefであれば、RangeのValueに値が入りますが、
ByValの場合は、Variant変数のRangeは破棄され、値そのものが変数に入ってしまいます。
これは、プロシージャー内でVariant変数を定義している場合を考えれば当然の結果として理解できます。
Set v = Rangeオブジェクト
v.Value = 1 '①
v = 1 '②
①では、Rangeオブジェクトの全てのValueに値(1)が入ります。
②では、変数vに値(1)そのものが入ります。
ByValで受け取った場合は、プロシージャー内で変数定義したことと同じになります。
Call sample_sub(rng1, rng2)
Sub sample_sub(ByRef v1, ByVal v2)
v1 = 1 '①
v2 = 1 '②
①では、Rangeオブジェクトの全てのValueに値(1)が入ります。
②では、変数vに値(1)そのものが入ります。
v2は、1がVariant/Integerとして代入されます。
結果として、
Sum(Range("A1:B1"), 1)
となるので、答えは3となります。
「VBAのVariant型について」
https://excel-ubara.com/excelvba4/EXCEL_VBA_441.html
同じテーマ「ツイッター出題回答 」の記事
VBAのString型の最大文字数について
Variantの数値型と文字列型の比較
Variant仮引数にRange.Valueを配列で渡す方法
Variant仮引数のByRefとByValの挙動違い
100桁の正の整数値の足し算
「VBA Match関数の限界」についての誤解
VBAで数値を漢数字に変換する方法
囲碁で相手の石を囲んで取るアルゴリズム
VBAで「3Lと5Lのバケツで4Lの水を作る」を解く
言語依存の関数を使用できるFormulaLocal
配列のUBoundがLBoundがより小さいことはあり得るか
新着記事NEW ・・・新着記事一覧を見る
ByRef引数の型が一致しません。|ツイッター出題回答 (2023-09-22)
シートコピー後のアクティブシートは何か|ツイッター出題回答 (2023-09-19)
Excel関数の引数を省略した場合について|ツイッター出題回答 (2023-09-14)
セル個数を返すRange.CountLargeプロパティとは|VBA技術解説(2023-09-08)
記号を繰り返してグラフ作成(10単位で折り返す)|ツイッター出題回答 (2023-08-28)
シートを削除:不定数のシート名に対応|VBAサンプル集(2023-08-24)
ランクによりボイントを付ける(同順位はポイントを分割)|ツイッター出題回答 (2023-08-22)
OneDrive使用時のThisWorkbook.Pathの扱い方|VBA技術解説(2023-07-26)
列幅不足による###表示や指数表示を判定する|VBA技術解説(2023-07-12)
シートを削除:不定数のシート名に対応|VBAサンプル集(2023-07-04)
アクセスランキング ・・・ ランキング一覧を見る
1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.繰り返し処理(For Next)|VBA入門
4.変数宣言のDimとデータ型|VBA入門
5.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
6.マクロとは?VBAとは?VBAでできること|VBA入門
7.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
8.並べ替え(Sort)|VBA入門
9.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
10.条件分岐(IF)|VBA入門
このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。