Как передать ошибку в пользовательской форме VBA вызывающему методу

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

Пользовательские формы VBA содержат событие с именем userform_error, которое определяется как

Private Sub UserForm_Error(
    ByVal Number As Integer, 
    ByVal Description As MSForms.ReturnString, 
    ByVal SCode As Long, 
    ByVal Source As String, 
    ByVal HelpFile As String, 
    ByVal HelpContext As Long, 
    ByVal CancelDisplay As MSForms.ReturnBoolean
)

Кажется логичным, что событие UserForm_Error вызывается при возникновении ошибки в пользовательской форме, но, похоже, это не так. На самом деле я не могу найти никакой документации для Userform_Error.

Я искал MSDN, Bing, Google, StackOverflow, DuckDuckGo, и мне не удалось найти хороший метод или какую-либо документацию о том, что на самом деле делает UserForm_error.


person lfrandom    schedule 04.06.2013    source источник
comment
Эксель VBA? Доступ к VBA? Можете ли вы привести пример с кодом, что вы пытаетесь сделать?   -  person shahkalpeshp    schedule 05.06.2013
comment
Это не приложение Microsoft Office.   -  person lfrandom    schedule 05.06.2013
comment
Я пытаюсь создать макрос с пользовательской формой. События в пользовательской форме могли иметь ошибку. Я бы хотел, чтобы об этой ошибке сообщалось основному модулю вместо того, чтобы встраивать обработчик ошибок в каждое событие в форме.   -  person lfrandom    schedule 05.06.2013
comment
Я не думаю, что это возможно. Сколько у вас событий, для которых вы не хотите писать обработчик ошибок?   -  person shahkalpeshp    schedule 05.06.2013
comment
Каждая кнопка в форме при нажатии теоретически может вызвать ошибку, поскольку все они зависят от DLL. В конце концов, у меня очень мало уязвимостей, так как уровень представления довольно хорошо отделен от других слоев, но мысль о написании обработчика ошибок, чтобы не дать неожиданной ошибке укусить меня за каждую кнопку и поле, обескураживает.   -  person lfrandom    schedule 05.06.2013
comment
Сколько таких внешних функций/методов вызывается при нажатии кнопки? Что вы могли бы сделать, так это написать методы, которые действуют как оболочки для этих внешних функций DLL, фиксируют ошибку для регистрации.   -  person shahkalpeshp    schedule 05.06.2013
comment
Событие ошибки вызывается только в том случае, если редактор VBA недоступен, например. в Access, если вы создадите MDE и форсируете ошибку, скажем, разделите 1 на 0 в Button_Click-Event, Error-Event сработает и перехватит ошибку, однако, если вы спровоцируете ошибку в обычном MDB-файле, VBA-Editor будет просто удерживать строку, в которой произошла ошибка, как обычно.   -  person AKDADEVIL    schedule 30.07.2013
comment
Это имеет смысл, к сожалению, в моей среде я не смогу использовать это конкретное событие.   -  person lfrandom    schedule 30.07.2013
comment
Согласно файлу справки, это событие возникает только в том случае, если элемент управления не может обработать ошибку. Вы можете увидеть файл справки, открыв браузер объектов -> «MSForms» в раскрывающемся списке -> выберите «UserForm» в списке классов, а затем щелкните правой кнопкой мыши событие «Ошибка».   -  person kb_sou    schedule 30.07.2013


Ответы (3)


Трудно дать вам точную информацию об этом, компонент древний. Просто какой-то фон.

Объект UserForm реализован Microsoft Forms 2.0, библиотекой компонентов ActiveX. Это была библиотека общего назначения для добавления форм в любое приложение, а не только приложения Office. Вы можете найти его на своем компьютере в c:\windows\syswow64\fm20.dll (system32 для 32-разрядной машины). Документация для этого компонента раньше поставлялась fm20.chm. Этот файл справки больше недоступен в Microsoft, вы все еще можете найти его с помощью запроса Google. Однако большинство сайтов, предлагающих его, выглядят очень подозрительно. Этот выглядел наименее скользким. На самом деле просмотр этого файла довольно проблематичен, я могу просматривать оглавление, но ни на одной из страниц больше не отображается текст.

Один обходной путь, который я нашел, заключался в декомпиляции файла с помощью утилиты HTML Workshop. Это создало файл с именем f3evtError.htm, он выглядит так (отредактировано для содержания):


Событие ошибки

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

Синтаксис

Private Sub object_Error( ByVal Number As Integer, ByVal Description As MSForms.ReturnString, _
    ByVal SCode As SCode, ByVal Source As String, ByVal HelpFile As String, _
    ByVal HelpContext As Long, ByVal CancelDisplay As MSForms.ReturnBoolean)

Синтаксис события Error состоит из следующих частей:

  • объект: Требуется. Допустимое имя объекта.
  • индекс: требуется. Индекс страницы в MultiPage, связанный с этим событием.
  • Номер: Требуется. Задает уникальное значение, которое элемент управления использует для идентификации ошибки.
  • Описание: Требуется. Текстовое описание ошибки.
  • SCode: требуется. Указывает код состояния OLE для ошибки. Младшие 16 бит задают значение, идентичное аргументу Number.
  • Источник: Обязательно. Строка, идентифицирующая элемент управления, инициировавший событие.
  • Файл справки: требуется. Задает полное имя пути к файлу справки, описывающему ошибку.
  • Контекст справки: требуется. Задает идентификатор контекста раздела файла справки, содержащего описание ошибки.
  • Отмена отображения: требуется. Указывает, отображать ли строку ошибки в окне сообщения.

Примечания

Код, написанный для события Error, определяет, как элемент управления реагирует на состояние ошибки.

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


Вот и все, к сожалению. Это расплывчато, потому что компонент может использоваться во многих различных типах хостов ActiveX, а перехват ошибок является деталью реализации хоста. Я думаю, что последний абзац - это то, о чем вы действительно спрашиваете. Я бы сказал, что можно с уверенностью предположить, что, поскольку в документации Office это не упоминается, приложения Office на самом деле не вызывают это событие. Тот факт, что событие по-прежнему отображается в редакторе VBA, является лишь побочным эффектом работы объектной модели. У редактора нет простого способа отфильтровать его, он просто отображает все опубликованные события объекта.

person Hans Passant    schedule 06.08.2013

Итак, я изучил это, потому что у меня была такая же проблема. Очень странно о событии ошибки, но я смог найти некоторую информацию об этом. Если вы ищете Событие ошибки в Справочнике разработчика в среде IDE, но не в автономном контенте, онлайн-контент. Вот что они говорят: «Происходит, когда элемент управления обнаруживает ошибку и не может вернуть информацию об ошибке вызывающей программе... Событие Error инициируется, когда возникает ошибка, которую приложение не может обработать». Теперь это наводит меня на мысль, что это событие возникает только тогда, когда происходит какая-то катастрофическая ошибка. Так что, похоже, вам не повезло с этим.

Невозможно вывести ошибку из-за неосновного кода введите здесь описание изображения

Мой способ обойти это заключался в том, чтобы каждая пользовательская форма имела свой собственный механизм обработки ошибок, что немного раздражает, но это лучшее, что я мог сделать. Кроме этого, в некотором свете, и я имею в виду очень легкий и не имел/ограниченного взаимодействия с системой, я смог сделать Возобновить при ошибке Далее в начале кода и как только я выгрузил пользовательскую форму проверил If Err.Number>0 Then Err.Raise Err.Number, поэтому обработчик ошибок его ловит. Однако, как вы, наверное, знаете, если вы выберете второй вариант, будьте осторожны.

Надеюсь, это поможет. Дай мне знать, что ты решишь.

person Justin    schedule 06.08.2013

Вы можете перехватывать ошибки в своем коде UserForm (который является классом), а затем в своем коде перехвата ошибок передавать сведения об ошибке в свой основной код, вызывая процедуру в модуле.

В качестве альтернативы вы можете объявить свою переменную UserForm WithEvents в ее вызывающем коде и вызвать собственное событие ошибки при возникновении ошибки.

person Monty Wild    schedule 01.08.2013
comment
Я боюсь, что невозможно объявить переменную UserForm WithEvents в стандартном модуле, она не будет компилироваться: Ошибка компиляции: допустимо только в объектном модуле. - person Daniel Dušek; 01.08.2013
comment
Извините, я предполагал, что вы вызываете его из другой формы, которая является модулем класса. Тогда вам нужно выбрать первый вариант. - person Monty Wild; 02.08.2013