Каковы правила использования скобок в вызовах функций VBA? - PullRequest
33 голосов
/ 24 марта 2011

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

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

Ответы [ 6 ]

55 голосов
/ 20 марта 2013

В 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.)

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

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

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

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

22 голосов
/ 24 марта 2011

С Здесь :

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

Call MySubroutine

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

Call MySubroutine(intUsageFee, intTimeInHours, "DevGuru") 

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

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

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

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

returnval = MyFunction
returnval = MyFunction()
returnval = MyFunction(intUsageFee, intTimeInHours, "DevGuru") 
7 голосов
/ 30 октября 2012

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

5 голосов
/ 13 апреля 2012

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

CallMe(argument)

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

Call CallMe(argument)

или

CallMe argument

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

3 голосов
/ 24 марта 2011

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

2 голосов
/ 24 сентября 2014

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

MsgBox "Hello World"

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

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

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

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»

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...