ツイッター出題回答
Variant仮引数のByRefとByValの挙動違い

ExcelマクロVBAとエクセル関数についての私的雑感
公開日:2020-07-05 最終更新日:2020-07-05

Variant仮引数のByRefとByValの挙動違い


ツイッターで出したVBAのお題です。
Variant型は、どんなデータ型も入れることができてしまいます。
具体的なデータ型の代わりに使用することで、より柔軟にVBA記述ができるようになります。
ただしこの便利さゆえに、逆に注意しなければならない挙動もあります。


お題のツイート

https://twitter.com/yamaoka_ss/status/1279642196430356487

【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

VBA マクロ Variant ByRef ByVal 挙動違い

解説のツイート

以下で一連の解説ツイートをしています。

https://twitter.com/yamaoka_ss/status/1279781207975182337


Variantの仮引数に対して実引数でRangeオブジェクトを指定した場合、
ByRef、ByVal、呼ばれた関数ではどちらもRangeオブジェクトとして受け取ります。
しかし、このときByRefとByValでは一部挙動に違いが現れます。
受け取ったRangeオブジェクトに対するVBA記述によって違いが出てきます。


仮引数のVariantでRangeオブジェクトを受け取った場合のByRefとByValでの挙動の違いは、
Set代入した場合には、
ByRefなら参照私として呼び出し元も変化しますが、
ByValなら受け取るだけであり呼び出し元は変化しません。


通常RangeオブジェクトのValueに値を入れる場合は、
Range = 値
このLet代入でRangeが複数セルでも全てのセルのValueに値が入ります。
仮引数がRange型(As Range)であれば、Let代入は同じ動作となります。
しかしVariantでRangeを受け取った場合は、Let代入で挙動に違いが出てきます。


仮引数のVariant変数に対するLet代入では、
ByRefであれば、RangeのValueに値が入りますが、
ByValの場合は、Variant変数のRangeは破棄され、値そのものが変数に入ってしまいます。
これは、プロシージャー内でVariant変数を定義している場合を考えれば当然の結果として理解できます。


Dim v
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)そのものが入ります。


v1は、Range("A1:B1")であり、全てのValueに1が入ります。
v2は、1がVariant/Integerとして代入されます。
結果として、
Sum(Range("A1:B1"), 1)
となるので、答えは3となります。

Variant変数の一般的な説明は、
「VBAのVariant型について」
https://excel-ubara.com/excelvba4/EXCEL_VBA_441.html
Variantデータ型は、他の何らかのデータ型として明示的に宣言されていない変数で、全てのデータ型を入れることができます。Variantデータ型には型宣言文字はありません。Variant型は、特別な値Empty、Error、Nothing、Nullを格納することもできます。




同じテーマ「ツイッター出題回答 」の記事

VBAのString型の最大文字数について

ツイッターで出したVBAのお題です。String型はVBAリファレンスでは、「可変長文字列は、最大で約20億(2^31)文字を格納できます。」と書かれています。これについて、本当は何文字まではいるのかについての問題です。
Variantの数値型と文字列型の比較
ツイッターで出したVBAのお題です。Variant型は、どんなデータ型も入れることができます。具体的なデータ型の代わりに使用することで、より柔軟にVBA記述ができるようになります。ただしその一方で、少々特殊な挙動もあり、使いこなすにはそれなりの知識が必要になる場合もあります。
Variant仮引数にRange.Valueを配列で渡す方法
ツイッターで出したVBAのお題です。Variant型は、どんなデータ型も受け入れることができます。RangeオブジェクトのValueを配列で受け取るにはVariant変数が必要です。ただし、実引数にRangeオブジェクトを直接指定する場合には注意が必要です。
Variant仮引数のByRefとByValの挙動違い
100桁の正の整数値の足し算
ツイッターで出したVBAのお題です。数の単位に「無量大数」というものがあります。VBAでこの無量大数の足し算をするにはどうしたら良いでしょうか。そこで、100桁の正の整数の足し算をVBAで実現してみましょう。
「VBA Match関数の限界」についての誤解
ツイッターで出したVBAのお題です。発端はエゴサーチからです。(笑) 「教えて!goo」で引用されていたのを見つけました。あちこちで引用されているのは見かけることはあるのですが、以下ではよく言うディスられているような文章を見かけました。
VBAで数値を漢数字に変換する方法
ツイッターで出したVBAのお題です。算用数字を漢数字に変換するVBAです。滅多に必要になるものではないのに、なぜこんな問題を出したかと言うと、最近シリーズで書き始めた「Excel将棋」で必要になったからです。
囲碁で相手の石を囲んで取るアルゴリズム
ツイッターで出したVBAのお題です。Excel囲碁を作っていて、相手の石を囲んで取れるかどうかの判定、相手の石を取るにはどうしたら良いかというもの。囲碁で相手の石をとる ここで、8二に黒を打てば、このように囲まれている白が取られます。
VBAで「3Lと5Lのバケツで4Lの水を作る」を解く
ツイッターでVBAのお題として出したものです。昔からよくある問題です。「3Lと5Lのバケツで4Lの水を作る」これをVBAを使って自動で求めてみようという事です。VBA問題:ツイートの記録 【VBA問題】 「3Lと5Lのバケツで4Lの水を作る」・2つの容器サイズは変えられるように引数で受け取る (3,5,
言語依存の関数を使用できるFormulaLocal
ツイッターでVBAのお題として出したものです。複数セルに一括で数式を入れるバ宇井の記述と、言語環境に依存する関数をセルに設定する場合のFormulaプロパティの使い方についての問題です。問題を出したツイート A1:A10セルに半角の英数文字が入っているので、これを全角で表示するためにB1:B10セルに数式をVBAで…
配列のUBoundがLBoundがより小さいことはあり得るか
ツイッターでVBAのお題として出したものです。配列の下限が上限より大きくなるような配列は存在するかの問題です。LBound(ary)>UBound(ary) この条件を満たすような配列は存在するか? 問題を出したツイート 配列の下限と上限を調べるにはLBound関数とUBound関数を使います。


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

ブール型(Boolean)のis変数・フラグについて|VBA技術解説(2024-04-05)
テキストの内容によって図形を削除する|VBA技術解説(2024-04-02)
ExcelマクロVBA入門目次|エクセルの神髄(2024-03-20)
VBA10大躓きポイント(初心者が躓きやすいポイント)|VBA技術解説(2024-03-05)
テンキーのスクリーンキーボード作成|ユーザーフォーム入門(2024-02-26)
無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)
累計を求める数式あれこれ|エクセル関数応用(2024-01-22)
複数の文字列を検索して置換するSUBSTITUTE|エクセル入門(2024-01-03)
いくつかの数式の計算中にリソース不足になりました。|エクセル雑感(2023-12-28)


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

1.最終行の取得(End,Rows.Count)|VBA入門
2.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
3.RangeとCellsの使い方|VBA入門
4.ひらがな⇔カタカナの変換|エクセル基本操作
5.繰り返し処理(For Next)|VBA入門
6.変数宣言のDimとデータ型|VBA入門
7.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
8.並べ替え(Sort)|VBA入門
9.セルのクリア(Clear,ClearContents)|VBA入門
10.Findメソッド(Find,FindNext,FindPrevious)|VBA入門




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


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


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