Каковы правила, регулирующие использование скобок в вызовах функций VBA?

У меня только что было 30 минут на раздражение "ошибки компилятора" в VBA (Access 2003), вызванное моим использованием скобок вокруг аргументов, которые я передаю в Sub I.

Я искал, чтобы найти достойную статью/учебник/инструкцию о том, когда скобки необходимы/соответствующие/неподходящие/запрещенные, но не могут найти четких рекомендаций.

6 ответов

Из Здесь:

Использование оператора VBScript для вызова подпрограммы Использование оператора вызова является необязательным, если вы хотите вызвать подпрограмму. Назначение оператора Call при использовании с Sub заключается в том, чтобы разрешить вам заключить список аргументов в круглые скобки. Однако, если подпрограмма не передает никаких аргументов, вы все равно не должны использовать круглые скобки при вызове Sub с помощью оператора Call.

Call MySubroutine

Если подпрограмма имеет аргументы, вы должны использовать круглые скобки при использовании оператора Call. Если есть несколько аргументов, вы должны разделить аргументы запятыми.

Call MySubroutine(intUsageFee, intTimeInHours, "DevGuru")

Вызов функции Существует два возможных способа вызова функции. Вы можете либо вызвать функцию напрямую, либо только по имени, либо вы можете вызвать ее, используя оператор VBScript Call.

Вызов функции по имени При вызове функции непосредственно по имени и при отсутствии присвоения возвращенному значению все следующие являются легальным синтаксисом:

MyFunction
MyFunction()
MyFunction intUsageFee, intTimeInHours, "DevGuru"

Если вы хотите получить возвращаемое значение, вы можете назначить функцию переменной. Обратите внимание, что если есть один или несколько аргументов, вы должны использовать круглые скобки.

returnval = MyFunction
returnval = MyFunction()
returnval = MyFunction(intUsageFee, intTimeInHours, "DevGuru")


В VB (A) существует идеальная логика для правила скобок в скобках, и это происходит следующим образом.

Если процедура (функция или под) вызывается с аргументами, а вызов находится в строке с другими операторами или ключевыми словами, аргументы должны быть заключены в круглые скобки. Это позволяет отличать аргументы, принадлежащие вызову процедуры от остальной части строки. Итак:

1: If CheckConditions(A, B, C) = DONT_PROCEED Then Exit Sub

- допустимая строка; вызов CheckConditions требует скобок, чтобы указать, какие другие биты строки являются его аргументами. И наоборот, это приведет к синтаксической ошибке:

2: If CheckConditions A, B, C = DONT_PROCEED Then Exit Sub

Потому что невозможно разобрать.

При вызове процедуры в качестве единственного оператора в строке скобки не нужны, потому что ясно, что аргументы принадлежат вызову процедуры:

3: SaveNewValues Value1, Value2, Value3

В то время как это приводит к синтаксической ошибке (по причинам, описанным ниже):

4: SaveNewValues(Value1, Value2, Value3)

Чтобы избежать путаницы в круглых скобках или без скобок (на самом деле, чтобы избежать правила круглых скобок полностью), всегда полезно использовать ключевое слово Call для таких вызовов; который гарантирует, что вызов процедуры не является единственным выражением в строке, что требует круглых скобок:

5: Call SaveNewValues(Value1, Value2, Value3)

Итак, если вы привыкли предшествовать автономным вызовам процедур с ключевым словом Call, вы можете забыть правило круглых скобок, потому что вы можете всегда заключать свои аргументы в круглые скобки.

Этот вопрос путают дополнительные круглые скобки в VB (A) (и многие другие языки): они также указывают приоритет оценки для выражений. Если вы используете круглые скобки в любом другом контексте, но для приложения аргументов вызова процедуры, VB (A) попытается оценить выражение в круглых скобках в результате простого значения.

Таким образом, в примере 4, где скобки являются незаконными для включения аргументов, VB (A) вместо этого попытается оценить выражение в круглых скобках. Поскольку (Value1, Value 2, Value3) не является выражением, которое может быть оценено, возникает синтаксическая ошибка.

Это также объясняет, почему вызовы с переменной, переданной ByRef, действуют так, как если бы они назывались ByVal, если аргумент заключен в круглые скобки. В приведенном выше примере, где функция p вызывается с параметром ByRef a, существует большая разница между этими двумя вызовами p:

6: p a

и

7: p(a)

Как обсуждалось выше, 6 является правильным синтаксисом: вызов один на его строке, поэтому круглые скобки не должны использоваться для включения аргументов.

В 7 аргумент заключен в круглые скобки в любом случае, в результате чего VB (A) оценивает прилагаемое выражение к простому значению. Это, конечно, само определение прохождения ByVal. Скобки гарантируют, что вместо указателя на a передается значение a, а a остается неизмененным.

Это также объясняет, почему правило круглых скобок не всегда кажется господствующим. Самый яркий пример - вызов MsgBox:

8: MsgBox "Hello World!"

И

9: MsgBox ("Hello World!")

Оба правильны, хотя правило скобок указывает, что 9 должно быть неправильным. Это, конечно, но все, что происходит, это то, что VB (A) оценивает выражение в круглых скобках. И строковый литерал оценивается с помощью одного и того же строкового литерала, так что фактический сделанный вызов равен 8. Другими словами: вызовы процедур с одним аргументом с константными или строковыми литералами имеют одинаковый результат с круглыми скобками или без них. (Вот почему даже моим вызовам MsgBox предшествует ключевое слово Call.)

Наконец, это объясняет нечетные ошибки несоответствия типа и странное поведение при передаче аргументов Object. Скажем, ваше приложение имеет процедуру HighlightContent, которая принимает аргумент TextBox как аргумент (и вы никогда не догадаетесь, выделяет его содержимое). Вы вызываете это, чтобы выбрать весь текст в текстовом поле. Вы можете вызвать эту процедуру тремя синтаксически правильными способами:

10: HighlightContent txtName
11: HighlightContent (txtName)
12: Call HighlightContent(txtName)

Скажем, ваш пользователь ввел "Джон" в текстовое поле, и ваше приложение вызывает HighlightContent. Что произойдет, какой вызов будет работать?

10 и 12 являются правильными; в текстовом поле будет выделено имя John. Но 11 синтаксически корректен, но приведет к ошибке компиляции или времени выполнения. Зачем? Потому что круглые скобки неуместны. Это побудит VB (A) попытаться оценить выражение в круглых скобках. И результат оценки объекта чаще всего будет значением его свойства по умолчанию;.Text, в этом случае. Поэтому вызов процедуры типа 11 не передаст объект TextBox процедуре, а строковое значение "Джон". Результат в несоответствии типов.


Я просто нашел какое-то странное поведение, вызывающее функцию с/без круглых скобок. Google взял меня сюда.

sub test()
 dim a as ******
 a = 1#
 p(a) 'this won't change a value
 Debug.Print a '1
 p a ' this is expected behavior
 Debug.Print a '2
 Call p(a) 'this is also valid
 Debug.Print a '3
end sub
Function p(a as ******) 'default is byref
 a = a + 1
end function

Мое заключение заключается в том, что при вызове функции с одним параметром вам нужно использовать либо "Вызов", либо "опустить" круглые скобки, иначе параметр не передается по ссылке (он все равно вызывается, как я уже проверял).


Я просто потратил 10 минут на выяснение исключения типа "несовместимое" при вызове Sub, который принимает 1 аргумент через

CallMe(argument)

Как оказалось, это неверно, googling приводит меня сюда и, наконец,

Call CallMe(argument)

или

CallMe argument

сделал трюк. Таким образом, вы не должны использовать скобки при вызове sub без оператора вызова, который принимает только один аргумент.


Когда вы используете Call MySub вы должны использовать круглые скобки вокруг параметров, но если вы опустите вызов, вам не нужны скобки.


1 - По умолчанию не используйте круглые скобки при вызове процедур или функций:

MsgBox "Hello World"

2 - Если вы вызываете функцию и интересуетесь ее результатом, вы должны заключить ее аргументы в круглые скобки:

Dim s As String
Dim l As Long 
s = "Hello World"
l = Len(s)

3 - Если вы хотите использовать ключевое слово для вызова с помощью процедуры, то вы должны заключить аргументы в круглые скобки (например, когда вы хотите назначить результат в переменной или использовать функцию в выражении):

Call MsgBox("Hello World")

4 - Если вы хотите, чтобы аргумент ByRef (по умолчанию) был передан ByVal, затем заключите аргумент ByRef с круглыми скобками:

Sub Test
 Dim text As String
 text = "Hello World"
 ChangeArgument((text))
 MsgBox text
End Sub
Sub ChangeArgument(ByRef s As String)
 s = "Changed"
End Sub

Отображается "Hello World"

licensed under cc by-sa 3.0 with attribution.