Автор Allen Browne, июнь 1997 г. Обновлено в сентябре 2009 г..

Оригинал http://allenbrowne.com/ser-23a.html

Перевел с английского Александр Артамонов, ноябрь 2011 г.


Обработка ошибок в VBA

В каждую функция или процедуру следует включать обработку ошибок. Без нее пользователь может оказаться глядящим на дефектный код в открытом редактороме VBA в полной версии Аксесс, а в рантайм версии приложение просто падает.. Более подробно обработка ошибок изложена в статье FMS  Error Handling and Debugging.

Простейший подход состоит в том, чтобы показать сообщение об ошибке и выйти из процедуры. Каждая процедура, таким образом, будет иметь такой формат (без номеров строк):

1 Sub|Function SomeName()
2 On Error GoTo Err_SomeName ' Инициализировать обработку ошибок.
3 'здесь должен быть ваш код.
4 Exit_SomeName: ' Метка для возобновления после ошибки.
5 Exit Sub|Function ' Выход до обработки ошибок.
6 Err_SomeName: ' Метка для перехода при ошибке.
7 MsgBox Err.Number & Err.Description ' Место для обработчика ошибок.
8 Resume Exit_SomeName ' возобновить код и выйти.
9 End Sub|Function

Для задач, где есть возможность нескольких ошибок, строки 7-8 нужно заменить более подробным вариантом:

      Select Case Err.Number
Case 9999 ' Номер ожидаемой ошибки.
Resume Next ' Чтобы игнорировать вызвавшую ошибку строку
Case 999
Resume Exit_SomeName ' Это используется для выхода из процедуры.
Case Else ' Любая неожиданная ошибка.
Call LogError(Err.Number, Err.Description, "SomeName()")
Resume Exit_SomeName
End Select

Ветка Case Else в этом примере вызывает пользовательскую функцию записи деталей ошибки в таблицу. Это позволит подробнее разобраться уже после того, как ошибка будет очищена. Таблицу можно назвать "tLogError" и состоять она будет из следующих полей:

Имя поля Тип данных Описание
ErrorLogID Счетчик Первичный ключ.
ErrNumber Число Длинное целое. Номер ошибки, сгенерированный Аксессом.
ErrDescription Текст Размер=255. Сообщение об ошибке, сгенерированное Аксессом.
ErrDate Дата/время Системная дата и время ошибки. По умолчанию: =Now()
CallingProc Текст Имя процедуры, вызвавшей LogError()
UserName Текст Имя пользователя.
ShowUser Логический Будет или нет показан диалоговое сообщение (MsgBox) c описанием ошибки
Parameters Текст 255. Опционально. Любые параметры, которые сочтете нужным записать.

 

Below is a procedure for writing to this table. It optionally allows recording the value of any variables/parameters at the time the error occurred. You can also opt to suppress the display of information about the error.

Ниже процедура для записи в эту таблицу. Она опционально позволяет записывать значения переменных/параметров во время возникновения ошибки. Можно также подавить вывод информации об ошибке на экран.


Function LogError(ByVal lngErrNumber As Long, ByVal strErrDescription As String, _
strCallingProc As String, Optional vParameters, Optional bShowUser As Boolean = True) As Boolean
On Error GoTo Err_LogError
' Назначение: Обобщенный обработчик ошибок.
' Записывает ошибки в таблицу "tLogError".
' Аргументы: lngErrNumber - значение Err.Number
' strErrDescription - значение Err.Description
' strCallingProc - имя процедуры/функции, сгенерировавшей ошибку.
' vParameters - необязательный параметр-строка: список параметров для записи в таблицу.
' bShowUser - необязательный параметр boolean: если False, подавляет вывод сообщения на экран.
' Автор: Allen Browne, allen@allenbrowne.com
Комментарии перевел Александр Артамонов

Dim strMsg As String ' Строковое значение для отображения в MsgBox
Dim rst As DAO.Recordset ' таблица tLogError

Select Case lngErrNumber
Case 0
Debug.Print strCallingProc & " called error 0."
Case 2501 ' Cancelled
'Do nothing.

Case 3314, 2101, 2115 ' Can't save.
If bShowUser Then
strMsg = "Record cannot be saved at this time." & vbCrLf & _
"Complete the entry, or press <Esc> to undo."
MsgBox strMsg, vbExclamation, strCallingProc
End If
Case Else
If bShowUser Then
strMsg = "Error " & lngErrNumber & ": " & strErrDescription
MsgBox strMsg, vbExclamation, strCallingProc
End If
Set rst = CurrentDb.OpenRecordset("tLogError", , dbAppendOnly)
rst.AddNew
rst![ErrNumber] = lngErrNumber
rst![ErrDescription] = Left$(strErrDescription, 255)
rst![ErrDate] = Now()
rst![CallingProc] = strCallingProc
rst![UserName] = CurrentUser()
rst![ShowUser] = bShowUser
If Not IsMissing(vParameters) Then
rst![Parameters] = Left(vParameters, 255)
End If
rst.Update
rst.Close
LogError = True
End Select

Exit_LogError:
Set rst = Nothing
Exit Function

Err_LogError:
strMsg = "В программе возникла непредвиденная ситуация." & vbCrLf & _
"Пожалуйста запишите следующую информацию:" & vbCrLf & vbCrLf & _
"Вызывающая процедура: " & strCallingProc & vbCrLf & _
"Номер ошибки " & lngErrNumber & vbCrLf & strErrDescription & vbCrLf & vbCrLf & _
"Запись в таблицу невозможна из-за Ошибки " & Err.Number & vbCrLf & Err.Description
MsgBox strMsg, vbCritical, "LogError()"
Resume Exit_LogError
End Function

Замечания по функции:

  1. Для Аксесса 1 или 2, используйте Access Basic error handler.
  2. Возвращаемое значение служит только с целью показать, успешно ли функция записала в лог ошибку.
  3. Возможные расширения: Поскольку таблица tErrorLog у вас уже открыта, вы могли бы посчитать последние ошибки и подавить вывод на экран одного и того же сообщения несколько раз, или отменить повторные ошибки блокировки.

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

Конструктор сайтов - uCoz