Ошибка компиляции VBA, если функция Instr используется с именованным параметром и возвращаемым значением, назначенным переменной

фон : в VBA, 'InStrRev' функция может вызываться без или с именованными параметрами.

    'Call without named parameters

     Call InStrRev("AB", "B")                   'No compiler error  
     i = InStrRev("AB", "B")                    'No compiler error

    'Call with named parameters

     Call InStrRev(StringCheck:="AB", StringMatch:="B") 'No compiler error
     i = InStrRev(StringCheck:="AB", StringMatch:="B")  'No compiler error

забота : в VBA компилятор возвращает ошибку "Expected: list separator", если'InStr':

  • вызывается с именованными параметрами и
  • возвращаемое значение присваивается переменной

    'Call without named parameters
    
     Call InStr("AB", "B")                   'No compiler error  
     i = InStr("AB", "B")                    'No compiler error
    
    'Call with named parameters
    
     Call InStr(String1:="AB", String2:="B") 'No compiler error
     i = InStr(String1:="AB", String2:="B")  'Compiler error : "Expected: list separator"
    

вопрос : Почему возникает ли ошибка компилятора VBA, когда'Instr' используется с именованными параметрами и ее возвращаемое значение присваивается переменной ? Это ограничение языка или ошибка компилятора ?

ссылка : скриншот редактора VBA для 'InstrRev' и 'Instr инструмент подсказки. Различия выделены красным цветом.

Comparison of '*InstrRev*' and '*Instr*' functions tips in VBA editor

Примечание : 'String1' & 'String2 'являются необязательными аргументами для'InStr' функция в соответствии с выше скриншот всплывающей подсказки квадратных скобок. Однако они необходимы, как указано ниже в ответе и в справочнике языка Visual Basic:https://msdn.microsoft.com/EN-US/library/office/gg264811.aspx

2 ответов


InStr странно в том, что его первый аргумент (Start) является необязательным, но его последующее String1/String2 аргументов нет (несмотря на [] в подсказке) - если они были дополнительно InStr(1) б анализировать но это не так и генерирует ту же ошибку, которую вы видите.

в частности, это странно, потому что VBA запрещает это; правило заключается в том, что необязательные аргументы не могут следовать необязательным аргументам, что имеет смысл, поскольку были бы случаи когда компилятор не смог сопоставить аргументы с тем, что ожидала функция. Это также заставляет все его аргументы быть вариантами.

VB6 / A имеет много багажа, перевезенного из QBASIC, и этот язык (который iirc не разрешал пользовательские необязательные аргументы) имеет точно такую же подпись для его INSTR() поэтому я предполагаю, что поведение, которое вы видите, является артефактом специальных правил синтаксического анализа, которые должны существовать для вызовов InStr.

любопытно его полностью полное имя

 i = VBA.Strings.InStr(String1:="AB", String2:="B")` 

не разобрать, но выдает ошибку во время выполнения, если Start предназначен:

i = VBA.Strings.InStr(String1:="AB", String2:="B", Start:=1)` 

, который работает, как ожидалось.

одной из причин Call форма может показаться, что работает, это ее no-op и может быть оптимизирована.


VBA.X () vs X ()

это прекрасно:

ptr = VBA.CLng(AddressOf someFunc)

это генерирует время разбора Ожидается, Что Выражение ошибка:

ptr = CLng(AddressOf someFunc)

InStr перегружен с помощью параметров варианта

на InStr функция имеет 4 необязательных параметра во время разработки, но во время выполнения должно быть предоставлено не менее 2 аргументов. Первые 3 параметра до InStr are все Variant, позволяющего InStr для поддержки двух разных синтаксисов и эффективной имитации перегруженной функции. Это одна из причин того, что String1 и String2 определяется как Variant типы, а не как String типы. Start может быть Long, но это Variant тоже тип.

в следующих 4 примерах,x и всегда присваивается значение 4

Вариант 1-использование определенного порядка параметров или имен-значения

сигнатура функции ведет себя так, как она определена:

Функция InStr ([Пуск], [String1], [String2], [Сравнить Как VbCompareMethod = vbBinaryCompare])

x = VBA.InStr(1, "food", "D", vbTextCompare)                                   '4
x = VBA.InStr(Start:=1, String1:="food", String2:="D", Compare:=vbTextCompare) '4

Вариант 2-использование альтернативного порядка или имени-значения

сигнатура функции ведет себя так, как если бы она была определена как:

функция InStr ([String1], [String2],, [сравнить как VbCompareMethod = vbBinaryCompare])

что фактически означает, что Start следует использовать так, как будто это String1 и String1 следует использовать, как если бы это String2. The String2 аргумент должны опустить, или вы получите Type Mismatch ошибка.

x = VBA.InStr("food", "D", , vbTextCompare)                        '4
x = VBA.InStr(Start:="food", String1:="D", Compare:=vbTextCompare) '4

Использование Именованных Параметров

но, как вы обнаружили,InStr функция страдает от синтаксиса и / или ошибок компиляции при использовании именованных параметров:

Синтаксическая Ошибка: Ожидается Разделитель

, когда все параметры им:

x = InStr(Start:=1, String1:="foo", String1:="foo", Compare:=vbBinaryCompare)

вы получить:

Синтаксическая Ошибка: Ожидается Разделитель

ошибка компиляции: объект не поддерживает именованные аргументы

, когда некоторые параметры им:

x = InStr(1, String1:="foo", String2:="foo", Compare:=vbBinaryCompare)

вы получаете:

ошибка компиляции: