Отладка. Печать в 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 "метод" этого "класса", чтобы иметь возможность отслеживать использование, как мы делаем с другими ранними ссылками на идентификаторы:

VBE7.DLL;  VBA.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 не найдена"

Другие вопросы по тегам