web-dev-qa-db-fra.com

Devrais-je utiliser le mot clé Call en VB/VBA?

J'utilise le mot clé Call lorsque j'appelle des sous-marins en VB/VBA. Je sais que c'est facultatif, mais est-il préférable de l'utiliser ou de ne pas l'utiliser? J'ai toujours pensé que c'était plus explicite, mais peut-être que c'est du bruit.

De plus, j'ai lu ceci sur un autre forum: L'utilisation du mot clé Call est plus rapide car il sait qu'il ne renverra aucune valeur. Il n'est donc pas nécessaire de configurer un espace de pile pour faire de la place à la valeur renvoyée.

42
Fred Loyant

Ah ah Je me suis longtemps posé la question à ce sujet et même en lisant un livre de deux pouces d'épaisseur sur VBA, vous ne devez pas l'utiliser, sauf si vous souhaitez utiliser la fonction Find du VBE pour rechercher facilement des appels dans de grands projets.

Mais je viens de trouver un autre usage.

Nous savons qu'il est possible de concaténer des lignes de code avec le caractère deux-points, par exemple:

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

Mais si vous faites cela avec des appels de procédure au début d'une ligne, le VBE suppose que vous faites référence à une étiquette et supprime les retraits, en alignant la ligne sur la marge de gauche (même si la procédure est appelée comme prévu):

Function Test()
Function1 : Function2
End Function

L'utilisation de l'instruction Call permet de concaténer des appels de procédure tout en conservant les retraits de code:

Function Test()
    Call Function1 : Call Function2
End Function

Si vous n'utilisez pas l'instruction Call dans l'exemple ci-dessus, le VBE supposera que "Function1" est une étiquette et l'aligne à gauche dans la fenêtre de code, même si cela ne provoque pas d'erreur.

25
Jamie Garroch

Pour VB6, s'il y a une chance qu'il soit converti en VB.NET, l'utilisation de Call signifie que la syntaxe ne change pas. (Les parenthèses sont obligatoires dans VB.NET pour les appels de méthode.) (Personnellement, je ne pense pas que cela vaille la peine; tout convertisseur .NET sera au moins capable de le mettre entre parenthèses lorsque cela est nécessaire. un motif.)

Sinon, ce n'est que du sucre syntaxique.

Notez que le mot clé Call ne sera probablement pas plus rapide lors de l'appel d'une autre méthode/fonction, car une fonction renvoie néanmoins sa valeur, et VB n'a pas eu besoin de créer une variable locale pour la recevoir, même lorsque Call est non utilisé.

11
Mark Hurd

J'utilise toujours Call dans VBA. Pour moi, ça a l'air plus propre. Mais, je suis d’accord, c’est juste du sucre syntaxique, ce qui en fait un domaine de prédilection. J'ai rencontré probablement une douzaine de gars de VBA à temps plein au cours des dernières années, et aucun d'entre eux n'a utilisé Call. Cela a eu l'avantage supplémentaire que j'ai toujours su quel code était le mien. : p

10
Nick Spreitzer

Non, il ne vous reste plus qu'à ajouter 7 caractères par appel, sans aucun avantage.

4
svinto

J'utilise Call pour tout développement VBA de fonctions de bibliothèque communes que j'utiliserai éventuellement dans VB.NET. Cela me permet de déplacer du code en utilisant copier/coller entre toutes les variantes de VB. Je fais cela pour éviter les erreurs de syntaxe que l'éditeur de code crée lorsqu'il "formate" ou "imprime joliment" le code collé. Les seules modifications sont généralement Set statement statement/exclusion.

Si vous n'envisagez pas de déplacer votre code VB/VBA vers VB.NET, il n'est pas nécessaire d'utiliser l'instruction Call.

3
AMissico

Si vous lisez la page Support MSDN pour Call Statement , pour le cas spécifique o VBA, au moins, cela indique que Call est facultatif, mais ce qui est très pertinent à ce sujet et que personne ne semble le remarquer est cette ligne citée:

"Si vous utilisez l'une des deux syntaxes d'appel pour appeler une fonction intrinsèque ou définie par l'utilisateur, la valeur de retour de la fonction est ignorée."

C'est pourquoi Call est loin d'être inutile. Supposons que vous écriviez des Sub SupportTasks qui font beaucoup de choses très pertinentes pour vous Principal Subs (par exemple, il importe des données d'un fichier pour qu'elles soient utilisées par différentes procédures). Maintenant, remarquez que, puisque SupportTasks lit des données externes, il y a toujours de fortes chances que ces données ne deviennent pas standard et que le sous-traitant ne puisse pas remplir son rôle. Que faire?

Vous pouvez, par exemple, utiliser des fonctions booléennes qui retournent False en cas de problème. Au lieu d'appeler un sous-marin, appelez une fonction SupportTasks inside et une instruction If qui quittera le sous-marin principal en cas d'anomalie:

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

Si vous vous demandez ce que cela a à voir avec Call, considérez les points suivants: dans un autre sous-dossier, j'appelle SupportTasks, mais je n'ai pas besoin de la valeur booléenne renvoyée (par exemple, Je suis certain qu'une erreur ne se produira pas). Eh bien, si je ne le mets pas dans une instruction If ou n'attribue la fonction à une variable inutile, VBA ne compilera pas et me renverra une erreur (appel de procédure invalide blah blah blah doit attribuer une valeur à quelque chose de bla bla bla). C'est là que Call entre pour sauver la situation!

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

Si vous pensez toujours que c'est inutile, considérez-le comme une ressource pour rester organisé. L'écriture de procédures distinctes pour des routines partagées par de nombreuses procédures rend votre code plus court et plus compréhensible, en particulier lorsque vous écrivez de très grandes applications. Les progiciels de gestion intégrés aux intégrations Excel-Access, par exemple, peuvent être plus faciles à utiliser, à réparer et à personnaliser si votre département informatique tarde à fournir/implémenter le système réel ...

Pour conclure, un peu de sagesse Internet:

_ {Écrivez toujours votre code comme si la personne qui l'examinera est un psychopathe meurtrier qui sait où vous habitez.

Amen.

3
FCastro

Personne n'a couvert cette distinction importante: dans certaines situations (courantes), Call empêche les parenthèses entourant les arguments de fonction (et de sous-arguments) de faire en sorte que les arguments soient interprétés strictement comme étant ByVal.

Le grand avantage pour vous est que si vous utilisez des parenthèses autour des arguments d'une routine, peut-être par cœur ou par habitude, même s'ils ne sont pas obligatoires, vous DEVREZ UTILISER Call pour vous assurer que la routine implicite ou explicite ByRef n'est pas ignorée. de ByVal; ou, au lieu de cela, vous devez utiliser une affectation "signe égal" de la valeur de retour pour éviter le non-respect (auquel cas vous ne voudriez pas utiliser Call).

Encore une fois, c'est pour vous protéger de ne pas obtenir ByVal défavorablement d'une routine. Inversement, bien sûr, si vous VOULEZ l’interprétation de ByVal quelle que soit la déclaration de la routine, quittez l’APPEL (et utilisez des parenthèses).

Justification: résumé https://msdn.Microsoft.com/en-us/library/ee478101%28v=vs.84%29.aspx "Paramètres ByRef et ByVal"

Si
1. il y a une assignation d'un appel de fonction retval, e. g.
iSum = myfunc (myArg)
ou
2. "Appel" est utilisé, e. g.
appeler myFunc (myArg)
ou
appelez mySub (myArg)

alors les parenthèses délimitent strictement la liste des arguments de l'appelant; la déclaration de routine détermine ByVal ou ByRef. AUTREMENT, les parenthèses obligent ByVal à être utilisé par la routine - même si ByVal n'était pas spécifié dans la routine. Ainsi,
mySub (myArg) 'utilise ByVal indépendamment de la déclaration de la routine
tandis que
Call mySub (myArg) 'utilise ByRef, à moins que la routine ne déclare ByVal

Notez également que Call syntaxiquement appelle l'utilisation de parenthèses. Tu peux y aller
mySub myArg
mais vous ne pouvez pas y aller
appelez mySub myArg
mais vous POUVEZ aller
appelez mySub (myArg)
(et les parenthèses sont syntaxiquement requises pour l'affectation de la valeur de retour de la fonction)

NOTE cependant que ByVal sur la déclaration de routine annule tout cela. Et pour info, ByRef est toujours impliqué dans la déclaration si vous êtes silencieux; TMK ByRef n'a donc aucune valeur apparente autre que le documentaire.

Répéter par le haut: le gros avantage pour vous est que si vous utilisez des parenthèses autour des arguments d'une routine, peut-être par cœur ou par habitude, même s'ils ne sont pas obligatoires, vous DEVREZ UTILISER Call pour vous assurer que la routine implicite ou explicite ByRef est pas négligé en faveur de ByVal; ou, au lieu de cela, vous devez utiliser une affectation "signe égal" de la valeur de retour pour éviter le non-respect (auquel cas vous ne voudriez pas utiliser Call).

Encore une fois, c'est pour vous protéger de ne pas obtenir ByVal défavorablement d'une routine. Inversement, bien sûr, si vous VOULEZ l’interprétation de ByVal quelle que soit la déclaration de la routine, quittez l’APPEL (et utilisez des parenthèses).

Le seul cas où j'ai trouvé "call" utile est tout à fait un hasard, à propos de certains opérateurs spéciaux.

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

J'ai eu une erreur de syntaxe pour la deuxième ligne, comme ce que vous obtiendrez avec un opérateur "New". Je ne veux vraiment pas de nouvelle variable, qui est trop inélégante pour moi. Alors j'ai essayé:

DirectCast(Await c, StartupTask).Disable()

Ceci est syntaxiquement correct. Mais alors le IDE m'a laissé entendre que le "DirectCast" est inutile et a donné une simplification. Oui, c'est:

Call (Await c).Disable()

C'est pourquoi j'aime VS2017 Preview. ????

1
强盗鼠

Je suis 7 ans en retard à la fête, mais je viens de tomber sur le mot clé Call il y a quelques minutes alors que je lisais quelque chose sur MSDN. En particulier, il était utilisé pour faire quelque chose que je pensais impossible dans VB.NET (par opposition à C #) - ce qui est lié à la réponse de @ FCastro.

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

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

Dans certains cas, vous n'avez pas besoin de l'instance d'objet mais de l'une de ses méthodes. Vous pouvez utiliser Call pour enregistrer une ligne. Notez que cela n’est pas nécessaire quand il s’agit du côté droit d’une opération:

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

Ancien fil de discussion, mais je ne vois pas qui ait couvert cette distinction importante: dans certaines situations (courantes), Call empêche les parenthèses entourant les arguments de fonction (et de sous) de faire en sorte que les arguments soient interprétés de manière stricte en tant que ByVal.

Le grand avantage pour vous est que si vous utilisez des parenthèses autour des arguments d'une routine, peut-être par cœur ou par habitude, même s'ils ne sont pas obligatoires, vous DEVREZ UTILISER Call pour vous assurer que la routine implicite ou explicite ByRef n'est pas ignorée. de ByVal; ou, au lieu de cela, vous devez utiliser une affectation "signe égal" de la valeur de retour pour éviter le non-respect (auquel cas vous ne voudriez pas utiliser Call).

Encore une fois, c'est pour vous protéger de ne pas obtenir ByVal défavorablement d'une routine. Inversement, bien sûr, si vous VOULEZ l’interprétation de ByVal quelle que soit la déclaration de la routine, quittez l’APPEL (et utilisez des parenthèses).

Justification: résumé https://msdn.Microsoft.com/en-us/library/ee478101%28v=vs.84%29.aspx "Paramètres ByRef et ByVal"

Si
1. il y a une assignation d'un appel de fonction retval, e. g.
iSum = myfunc (myArg)
ou
2. "Appel" est utilisé, e. g.
appeler myFunc (myArg)
ou
appelez mySub (myArg)

alors les parenthèses délimitent strictement la liste des arguments de l'appelant; la déclaration de routine détermine ByVal ou ByRef. AUTREMENT, les parenthèses obligent ByVal à être utilisé par la routine - même si ByVal n'était pas spécifié dans la routine. Ainsi,
mySub (myArg) 'utilise ByVal indépendamment de la déclaration de la routine
tandis que
Call mySub (myArg) 'utilise ByRef, à moins que la routine ne déclare ByVal

Notez également que Call syntaxiquement appelle l'utilisation de parenthèses. Tu peux y aller
mySub myArg
mais vous ne pouvez pas y aller
appelez mySub myArg
mais vous POUVEZ aller
appelez mySub (myArg)
(et les parenthèses sont syntaxiquement requises pour l'affectation de la valeur de retour de la fonction)

NOTE cependant que ByVal sur la déclaration de routine annule tout cela. Et pour info, ByRef est toujours impliqué dans la déclaration si vous êtes silencieux; TMK ByRef n'a donc aucune valeur apparente autre que le documentaire.

Répéter par le haut: le gros avantage pour vous est que si vous utilisez des parenthèses autour des arguments d'une routine, peut-être par cœur ou par habitude, même s'ils ne sont pas obligatoires, vous DEVREZ UTILISER Call pour vous assurer que la routine implicite ou explicite ByRef est pas négligé en faveur de ByVal; ou, au lieu de cela, vous devez utiliser une affectation "signe égal" de la valeur de retour pour éviter le non-respect (auquel cas vous ne voudriez pas utiliser Call).

Encore une fois, c'est pour vous protéger de ne pas obtenir ByVal défavorablement d'une routine. Inversement, bien sûr, si vous VOULEZ l’interprétation de ByVal quelle que soit la déclaration de la routine, quittez l’APPEL (et utilisez des parenthèses).