Отладка. Печать в VBA
В VBA Debug.Print
печатает в ближайшее окно.
Я только что узнал, что с помощью точки с запятой (;
) печатает в позиции курсора / текстового курсора, что кажется странным.
Debug.Print "a" & "b" & "c"
Debug.Print ; "a"; "b"; "c"
Debug.Print "a", "b", "c"
Печатает следующее.
abc
abc
a b c
Это был мой главный вопрос, прежде чем я нашел его в документации и понял немного больше.
Мой вопрос сейчас заключается в том, можно ли использовать именованный аргумент, например так:
Debug.Print object:="..."
Intellisense обычно помогает найти имена аргументов, но не содержит их.
Я тоже пробовал object
или же outputlist
как это показано в документации, но выдает ошибку.
Является Debug.Print
отличается в этом отношении?
1 ответ
Debug
заявления действительно отличаются от всего остального. Если вы ищете Debug
Модуль в обозревателе объектов, вы не найдете его, даже если скрытые классы и члены показаны.
Debug.Print
а также Debug.Assert
операторы буквально встраиваются в сам язык [parser] - запятая здесь не означает "разделитель аргументов", вместо этого это синтаксис специальной формы, который [очевидно] зарезервирован для Print
методы (примечание: пользовательский код VBA не может использовать Print
для имени метода оно зарезервировано).
Так Debug
заявления в основном особые виды ключевых слов. Краткая информация IntelliSense / параметра показана для элементов синтаксиса списка аргументов, но синтаксически - "аргументы" Debug.Print
являются выходным списком, точно так же, как оператор Print.
Обратите внимание, что VBE автоматически поворачивает ?
знак в Print
заявление:
Debug.? --> Debug.Print
Там довольно много исторического багажа с Print
: ключевое слово / команда (и его ?
сокращение) использовалось в старых диалектах BASIC для вывода вещей на экран... или на настоящий [матричный матричный!] принтер.
Итак, короткий ответ: Debug
утверждения делаются с ключевыми словами, а не с вызовами участников, и именно поэтому IntelliSense с ними бесполезен, поскольку аргументов нет.
У проекта Rubberduck есть забавная история с этими утверждениями... потому что на самом деле невозможно разобрать типичный Debug.Print
заявление по-другому, чем любой другой неявный callStmt
(т.е. он выглядит и анализируется как любой другой вызов процедуры), мы должны были дать оператору свое собственное правило синтаксического анализатора и "объявить" подделку DebugClass
модуль и сделать Print
"метод" этого "класса", чтобы иметь возможность отслеживать использование, как мы делаем с другими ранними ссылками на идентификаторы:
Но на самом деле такого нет: операторы со списком вывода запекаются в язык на уровне парсера и компилятора, тогда как буквально каждый вызов члена, который вы когда-либо делали в VBA, был членом какого-то модуля - нажмите F2 и просмотрите члены стандартной библиотеки VBA: вы найдете CLng
преобразование типов, Now
а также DateAdd
функции даты / времени, MsgBox
, DoEvents
и многие другие - все они принадлежат какому-то модулю. Но Debug
заявления ближе к Stop
или же Resume
ключевое слово, обрабатывается на более низком уровне.
Еще одно доказательство того, что есть нечто большее, чем кажется на первый взгляд - кроме простого факта, что подсветка синтаксиса по умолчанию в VBE выделит оба Debug
а также Print
в ярком синем ключевом слове, если вы компилируете COM-видимый класс, написанный на C#:
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("6F25002E-2C9F-4D77-8CCB-A9C0E4FB2EF1")]
public interface ITestClass
{
[DispId(1)]
void Print(string value);
[DispId(2)]
void DoSomething();
}
[ComVisible(true)]
[ComDefaultInterface(typeof(ITestClass))]
[ClassInterface(ClassInterfaceType.None)]
[Guid("6F25002E-2C9F-4D77-9624-6CA79D4F088A")]
[ProgId("PrintTest.Class1")]
[EditorBrowsable(EditorBrowsableState.Always)]
public class Class1 : ITestClass
{
public void Print(string value)
{
/* no-op */
}
public void DoSomething()
{
/* no-op */
}
}
..и затем вызвать его из кода VBA...
DoSomething
метод может быть вызван, но Print
Метод выдаст ошибку 438 - так же, как если бы вы попытались квалифицировать его с чем-либо, кроме Debug
, Так как же Print
работает в коде доступа отчета тогда?
Интерфейс не задокументирован, так что это чисто предположение, но есть IVBPrint
интерфейс, который очень похож на то, что VBA будет искать:
[
odl,
uuid(000204F0-0000-0000-C000-000000000046),
nonextensible
]
interface IVBPrint : IUnknown {
HRESULT _stdcall WriteText([in] BSTR strText);
[propput]
HRESULT _stdcall Column([in] long retVal);
[propget]
HRESULT _stdcall Column([out, retval] long* retVal);
};
Если это так, то ошибка 438 - это просто способ VBA сказать "реализация IVBPrint не найдена"