Мне не удается использовать оператор Bang (!) Без жестко заданного аргумента, т. Е. Me.VBProject.References!Excel. В этом примере ссылка Excel жестко закодирована. Из-за разочарования я перепробовал все возможные варианты, пытаясь использовать его:

[Me.VBProject.References!(str)]
[Me.VBProject.References! & (str)]
["Me.VBProject.References!" & str]
["Me.VBProject.References!" & (str)]

И многое другое с добавлением скобок для обеспечения правильной предварительной оценки, включая метод long Application.evaluate. Нада !

3
IronX 6 Апр 2017 в 01:58

2 ответа

Лучший ответ

Нет, ты не можешь этого сделать.

Оператор bang - это просто ярлык для вызова члена объекта по умолчанию и передачи текста после взрыва в виде строки первому параметру члена по умолчанию:

Нотация взрыва:

Me.VBProject.References!Excel

В точности эквивалентно:

Me.VBProject.References.Item("Excel")

И, поскольку это элемент по умолчанию, вы можете опустить вызов функции Item:

Me.VBProject.References("Excel")

Итак, чтобы использовать вашу (действительно плохо названную) переменную str:

str = "Excel"
Debug.Print Me.VBProject.References.Item(str).Name
5
Mathieu Guindon 6 Апр 2017 в 12:06

Это проблема X-Y.

Нотация взрыва является средством для достижения цели.

Это один из доступных вам инструментов для извлечения элемента из коллекции .

Ни больше ни меньше.

Вам не нужно использовать оператор bang с переменной .
Вам нужно извлечь элемент из коллекции, используя переменную .

Типы коллекций имеют член по умолчанию , обычно называемый Item. Члены по умолчанию могут быть указаны явно или неявно доступны:

Dim foo As New Collection
foo.Add Item:=42, Key:="test"
Debug.Print foo.Item("test") 'explicit reference to the default member
Debug.Print foo("test") 'implicit reference to the same default member

Оператор bang - это просто еще один способ неявного вызова члена коллекции по умолчанию:

Debug.Print foo!test

Все 3 Debug.Print оператора выше будут вызывать элемент по умолчанию foo.Item для вывода 42, связанного с ключом "test".

Квадратных скобках

Как вы можете видеть, сразу после оператора ! находится строковый литерал . Поскольку строковый литерал может содержать пробелы, парсеру VB6 / VBA необходим способ их поддержки.

Вот для чего [square brackets]:

foo.Add 72, "spaces in the key"
Debug.Print foo![spaces in the key]

Когда они не разграничивают строковый литерал для записи взрыва, квадратные скобки обычно 1 интерпретируются как выражение времени выполнения для оценки приложением хоста. Например, это допустимо (хотя и сомнительно желательно) в Excel VBA:

Debug.Print [A1]

Синтаксический анализатор VBA идентифицирует выражение в скобках и откладывает его оценку для хост-приложения - здесь Excel; во время выполнения инструкция в конечном итоге приравнивается к:

Debug.Print ActiveSheet.Range("A1").Value

Если вы не верите, что оценка выражения в квадратных скобках откладывается на хост-приложение, подумайте, что должно произойти, чтобы эта инструкция напечатала 4:

Debug.Print [Sum(2,2)]

Поэтому каждая попытка / перестановка в вашем сообщении не соответствовала цели и заставляла Excel пытаться оценить выражение, которое сможет разрешить только VBA, поскольку Me.VBProject.References абсолютно ничего не значит для Excel .

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


1 Обычно , поскольку они также могут использоваться в некоторых идентификаторах, например, в типах Enum, чтобы сделать член перечисления [_hidden].


Нижняя граница

Нотация Bang - это способ извлечь элемент из коллекции, используя члены по умолчанию и заставляя строковые литералы выглядеть как идентификатор. Вы не можете заставить его работать без «жесткого кодирования» строкового литерала, потому что он требует строкового литерала .

Если вы хотите параметризовать получение коллекции, вы не можете использовать оператор взрыва.

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


Примечание. Нотация взрыва не на самом деле предназначена только для коллекций. Он фактически передает свой аргумент в виде строкового литерала первому параметру всего, что имеет член по умолчанию. Однако я бы настоятельно рекомендовал избегать его для чего-либо, кроме класса коллекции (например, Collection.Item, Workbooks.Item, Worksheets.Item, Recordset.Fields и т. Д.), Ради будущих сопровождающих. здравомыслие.

2
Mathieu Guindon 6 Апр 2017 в 21:08