web-dev-qa-db-ja.com

VB / VBAでCallキーワードを使用する必要がありますか?

VB/VBAでサブを呼び出すときにCallキーワードを使用します。オプションであることはわかっていますが、使用するか、オフのままにした方がよいですか?私はいつもそれがより明白であると思っていましたが、おそらくそれは単なるノイズです。

また、私は別のフォーラムでこれを読みました:Callキーワードを使用すると、値が返されないことがわかっているため、より高速になり、戻りのためのスペースを作るためにスタックスペースを設定する必要がありません。値。

46
Fred Loyant

ああ。私はこれについて長い間思っていましたが、VBAで2インチの厚さの本を読んでも、大規模なプロジェクトで簡単に呼び出しを見つけるためにVBEのFind機能を使用したくない限り、基本的には使用しないと言っています。

しかし、私は別の用途を見つけました。

たとえば、次のように、コード行をコロン文字で連結できることがわかっています。

Function Test(mode as Boolean) 
    if mode = True then x = x + 1 : Exit Sub
    y = y - 1
End Sub

ただし、行の先頭でプロシージャコールを使用してこれを行うと、VBEはラベルを参照していると見なし、インデントを削除して、行を左マージンに揃えます(プロシージャは意図したとおりに呼び出されますが)。

Function Test()
Function1 : Function2
End Function

Callステートメントを使用すると、コードのインデントを維持しながら、プロシージャコールを連結できます。

Function Test()
    Call Function1 : Call Function2
End Function

上記の例でCallステートメントを使用しない場合、VBEは「Function1」がラベルであると想定し、エラーが発生しなくてもコードウィンドウで左揃えにします。

27
Jamie Garroch

VB6の場合、VB.NETに変換される可能性がある場合、Callを使用すると、構文は変更されません。 (VB.NETではメソッド呼び出しにかっこが必要です。)(私は個人的には、これが気になるほどの価値があるとは思いません-.NETコンバータは、必要に応じて少なくともかっこを入れることができます。理由。)

そうでなければ、それは単に構文上の砂糖です。

関数はとにかく値を返すため、他のメソッド/関数を呼び出す場合、Callキーワードの方が高速ではない可能性が高く、VBはローカル変数を作成する必要がないことに注意してください。 Callが使用されていない場合でも、それを受け取ります。

11
Mark Hurd

VBAでは常にCallを使用します。私には、それはきれいに見えます。しかし、私は同意します、それは単なる構文上の砂糖であり、個人の好みの領域を正直に表現します。私はおそらく過去数年で12人のフルタイムのVBAの人に出会いましたが、そのうちの1人はCallを使用していません。これには、自分がどのコードかを常に知っているという利点がありました。 :p

10
Nick Spreitzer

いいえ、通話ごとに7文字追加されるだけで、メリットはありません。

4
svinto

VB.NETで使用する可能性のある一般的なライブラリ関数のすべてのVBA開発にCallを使用します。これにより、VBのすべてのフレーバー間でコピーアンドペーストを使用してコードを移動できます。これは、貼り付けたコードを「フォーマット」または「きれいに印刷」するときにコードエディターが作成する構文エラーを回避するためです。通常、編集内容はSetステートメントの包含/除外のみです。

VB/VBAコードをVB.NETに移行する予定がない場合は、Callステートメントを使用する必要はありません。

3
AMissico

誰もこの重要な区別をカバーしていませんでした。一部の(一般的な)状況では、Callは関数(およびサブ)引数を囲む括弧が原因で引数がByValとして厳密に解釈されるのを防ぎます。

あなたにとって重要なことは、ルーチンへの引数の周りに括弧を使用する場合、たとえそれが必要ではないとしても、おそらくロートまたは習慣によって、ルーチンの暗黙的または明示的なByRefが優先的に無視されないことを保証するために呼び出しを使用する必要があるということです。 ByValの;または、代わりに、無視しないように戻り値の「等号」割り当てを使用する必要があります(この場合、Callは使用しません)。

繰り返しになりますが、これは、ルーチンからByValを不利に取得しないようにするためです。もちろん、逆に、ルーチンの宣言に関係なくByVal解釈が必要な場合は、呼び出しを省略し、括弧を使用します。

理論的根拠:要約 https://msdn.Microsoft.com/en-us/library/ee478101%28v=vs.84%29.aspx "ByRefおよびByValパラメータ"

もし
1。関数呼び出しretvalの割り当てがあります。 g。
iSum = myfunc(myArg)
または
2。 「呼び出し」が使用されます。 g。
myFunc(myArg)を呼び出す
または
mySub(myArg)を呼び出す

次に、括弧は呼び出し引数リストを厳密に示します。ルーチン宣言は、ByValまたはByRefを決定します。それ以外の場合、ByValがルーチンで指定されていなくても、括弧はByValをルーチンで使用することを強制します。したがって、
mySub(myArg) 'ルーチンの宣言に関係なく、ByValを使用します
一方
Call mySub(myArg) 'ルーチンがByValを宣言しない限り、ByRefを使用します

また、Callは構文的に括弧の使用を義務付けていることに注意してください。行ってもいい
mySub myArg
しかし、あなたは行くことができません
mySub myArgを呼び出す
しかし、あなたは行くことができます
mySub(myArg)を呼び出す
(および括弧は、関数の戻り値の割り当てに構文的に必要です)

ただし、ルーチン宣言のByValはこれをすべてオーバーライドすることに注意してください。そして参考までに、あなたが黙っていれば、ByRefは常に宣言に含まれます。したがって、TMK ByRefにはドキュメンタリー以外の明確な価値はありません。

上からの繰り返し:ルーチンの引数を括弧で囲んで(おそらくロートまたは習慣で)必要ない場合でも、括弧を使用する場合は、呼び出しを使用して、ルーチンの暗黙的または明示的なByRefがByValを支持して無視されません。または、代わりに、無視しないように戻り値の「等号」割り当てを使用する必要があります(この場合、Callは使用しません)。

繰り返しになりますが、これは、ルーチンからByValを不利に取得しないようにするためです。もちろん、逆に、ルーチンの宣言に関係なくByVal解釈が必要な場合は、呼び出しを省略し、括弧を使用します。

私が「電話」が役立つと思った唯一のケースは、いくつかの特別なオペレーターについてのかなりの事故です。

Dim c As IAsyncOperation(Of StartupTask) = StartupTask.GetAsync("Startup")
……
(Await c).Disable()

"New"演算子で得られるのと同じように、2行目の構文エラーが発生しました。私は本当に新しい変数を使いたくありません。だから私は試しました:

DirectCast(Await c, StartupTask).Disable()

これは構文的に正しいです。しかし、IDEは、「DirectCast」が不要であることをほのめかし、簡略化をもたらしました。はい、つまり:

Call (Await c).Disable()

だから私はVS2017 Previewが大好きです。 ????

1
强盗鼠

私はパーティーに7年遅れていますが、MSDNで何かを読んでいるときに、たまたま数分前にCallキーワードに遭遇しました。特に、(C#ではなく)VB.NETでは不可能だと思っていた処理に使用されていました-これは@FCastroの回答に関連しています。

Class Test
    Public Sub DoSomething()
        Console.WriteLine("doing something")
    End Sub
End Class

Sub Main()
    Call (New Test()).DoSomething()
End Sub

奇妙なケースでは、実際のオブジェクトインスタンスは必要ありませんが、そのメソッドの1つが必要な場合は、Callを使用して行を保存できます。操作の右側の場合、これは不要であることに注意してください。

Class Test
    Public Function GetSomething() As Integer
        Return 0
    End Function
End Class

Sub Main()
    Dim x As Integer = (New Test()).GetSomething()
End Sub
1
Brandon Hood

古いスレッドですが、この重要な違いをカバーしている人はいないと思います。一部の(一般的な)状況では、Callは関数(およびサブ)引数の周りの括弧が原因で引数がByValとして厳密に解釈されるのを防ぎます。

あなたにとって重要なことは、ルーチンへの引数の周りに括弧を使用する場合、それらが必要ではない場合でも、おそらくロートまたは習慣により、ルーチンの暗黙的または明示的なByRefが優先的に無視されないことを保証するために呼び出しを使用する必要があることです。 ByValの;または、代わりに、無視しないように戻り値の「等号」割り当てを使用する必要があります(この場合、Callは使用しません)。

繰り返しますが、これは、ルーチンからByValを不利に取得することから保護するためです。もちろん、逆に、ルーチンの宣言に関係なくByVal解釈が必要な場合は、呼び出しを省略します(括弧を使用します)。

理論的根拠:要約 https://msdn.Microsoft.com/en-us/library/ee478101%28v=vs.84%29.aspx "ByRefおよびByValパラメータ"

もし
1。関数呼び出しretvalの割り当てがあります。 g。
iSum = myfunc(myArg)
または
2。 「通話」が使用されます。 g。
myFunc(myArg)を呼び出す
または
mySub(myArg)を呼び出す

次に、括弧は呼び出し引数リストを厳密に示します。ルーチン宣言は、ByValまたはByRefを決定します。それ以外の場合は、ByValがルーチンで指定されていなくても、括弧によってByValがルーチンで使用されます。したがって、
mySub(myArg) 'ルーチンの宣言に関係なく、ByValを使用します
一方
Call mySub(myArg) 'ルーチンがByValを宣言しない限り、ByRefを使用します

また、Callでは括弧の使用が構文的に義務付けられています。行ってもいい
mySub myArg
しかし、あなたは行くことができません
mySub myArgを呼び出す
しかし、あなたは行くことができます
mySub(myArg)を呼び出す
(および括弧は、関数の戻り値の割り当てに構文的に必要です)

ただし、ルーチン宣言のByValはこれをすべてオーバーライドすることに注意してください。そして参考までに、あなたが黙っていれば、ByRefは常に宣言に含まれます。したがって、TMK ByRefにはドキュメンタリー以外の明確な価値はありません。

上からの繰り返し:ルーチンの引数を括弧で囲んで(おそらくロートまたは習慣で)必要ない場合でも、括弧を使用する場合は、呼び出しを使用して、ルーチンの暗黙的または明示的なByRefがByValを支持して無視されません。または、代わりに、無視しないように戻り値の「等号」割り当てを使用する必要があります(この場合、Callは使用しません)。

繰り返しますが、これは、ルーチンからByValを不利に取得することから保護するためです。もちろん、逆に、ルーチンの宣言に関係なくByVal解釈が必要な場合は、呼び出しを省略します(括弧を使用します)。

CallステートメントのMSDNサポートページ を読んだ場合、少なくともVBAの特定のケースでは、Callはオプションですが、それに関して非常に関連があり、誰も気づいていないように見えるのは、この引用された行です。

"組み込み構文またはユーザー定義関数を呼び出すために呼び出し構文を使用する場合、関数の戻り値は破棄されます。"

これがCallが役に立たない理由です。あなたがSub SupportTasksを書いているとしましょう---それはあなたに非常に関連性のある多くのことをしますMain Subs(たとえば、さまざまな手順で使用されるファイルからデータをインポートします) 。 SupportTasksが外部データを読み取っているので、このデータが標準にならず、潜水艦がその役割を果たせない可能性が常にあります。 あなたは何をしますか?

たとえば、何か問題が発生した場合にFalseを返すブール関数を使用できます。サブルーチンを呼び出す代わりに、内部に関数SupportTasksおよびIfステートメントを呼び出し、異常が発生した場合にMainサブルーチンを終了します。

If Not SupportTasks(SomeArgument) Then
    Application.ScreenUpdating = True
    Exit Sub
'Else continue the Main sub regularly without writing anything in here
End If

これがCallとどう関係しているのか不思議に思っている場合は、次のことを考慮してください。別のサブで、SupportTasksを呼び出します=、しかし、返されたブール値は必要ありません(たとえば、エラーが発生しないと確信しています)。まあ、それをIfステートメントに入れなかったり、関数を役に立たない変数に割り当てたりしないと、VBAはコンパイルせず、エラーを返します(procedure call invalid blah blah blah must何かに値を割り当てる何とか何とか何とか)。 Callがその日を救う場所です!

Call SupportTasks(SomeArgument) '<< "Call Function" call doesn't return an error

それでも役に立たないと思われる場合は、整理整頓のためのリソースと考えてください。多くのプロシージャで共有されているルーチンに対して個別のプロシージャを作成すると、コードがshortおよびよりわかりやすくなります、特に、非常に大きなアプリケーションを作成している場合。たとえば、ExcelとAccessの統合から構築されたERPは、IT部門が実際のシステムの配信/実装に時間がかかる場合に、操作、修復、カスタマイズが簡単になります...

結論として、いくつかのインターネットの知恵:

常に、コードをレビューする人が、あなたの住んでいる場所を知っている殺人精神病者であるかのようにコードを記述してください。

アーメン。

1
FCastro