-
Обработка ошибок на этапе выполнения
Как
тщательно не проверялся бы код, на этапе
его выполнения неизбежно возникают
ошибки. Попытка деления на ноль – это
типичный пример ошибки времени выполнения.
В Access обработка ошибок выполняется с
помощью инструкции On Error. Имеется три
вида инструкций On Error:
-
On Error GoTo Метка –
осуществляет переход на строку с меткой
(Метка) при возникновении произвольной
ошибки на этапе выполнения. Обычная
часть кода, обрабатывающая ошибки,
помещается в корпус процедуры. После
обработки ошибки можно либо вызвать
повторение той части кода, где произошла
ошибка, либо проигнорировать ошибку и
продолжить выполнение последующих
инструкций. Для возвращения на строку
с ошибкой используется ключевое слово
Resume. -
On
Error Resume Next – игнорирует ошибку и
продолжает выполнение последующих
инструкций. -
On
Error GoTo 0 отключает обработку ошибок.
После
обработки первой ошибки инструкция On
Error GoTo Метка продолжает выполняться для
всех последующих ошибок, пока не
закончится выполнение данной процедуры
либо обработка ошибок не будет явно
отключена инструкцией On Error GoTo 0. Если
нет обработки какой-то ошибки или
обработка выключена, то при возникновении
необработанной ошибки приложение сразу
же выдаст сообщение об ошибке и прекратит
работу.
Если
процедура обработки некоторого события
создается с помощью мастера, то он
автоматически дополняет процедуру
кодом обработки ошибок.
Private
Sub MyID_DblClick(Cancel As Integer)
On
Error GoTo Err_MyID_DblClick
Текст
процедуры
Exit_MyID_DblClick:
Exit
Sub
Err_MyID_DblClick:
MsgBox
Err.Description
Resume
Exit_MyID_DblClick
End
Sub
Объект
Err содержит информацию об ошибках
выполнения и обычно используется вместе
со структурой Select Case, чтобы определить,
какое действие предпринять в зависимости
от кода ошибки.
Select
Case Err
Case
58 To 76
Call
FileError- процедура обработки ошибок работы
с файлами
Case
281 To 297
Call
DDEError — процедура для обработки ошибок
DDE
Case
340 To 344
Call
ArrayError — процедура
ошибок
массивов
End
Select
Err=0
— отключение обработки необработанных
ошибок.
-
Работа с объектами и коллекциями
В
VBA можно работать с объектами и коллекциями
Access, библиотекой доступа к данным DAO
(Data Access Objects), библиотекой прямого доступа
к данным баз данных ODBC (ODBC Direct), библиотекой
доступа к данным ADO (ActiveX Data Objects) и другими
библиотеками. В Access, DAO и ADO все объекты
расположены внутри коллекций и доступны
в VBA. Каждый объект имеет свойства и
методы. Все библиотеки организованы в
виде иерархии объектов. Объекты имеют
коллекции (семейства) подчиненных
объектов и т.д. В Access имеется 8 базовых
объектов; их иерархия представлена на
Рис. 12.
Объекты
MS
Access:
-
Application – активное
приложение; -
Control
– элемент управления; -
DoCmd
– объект вызова макрокоманд в VBA коде; -
Form
– открытая форма; -
Module
– объект, ссылающийся на стандартные
модули; -
Reference
– объект, содержащий ссылки на объекты; -
Report
– открытый отчет; -
Screen
– ссылка на экран;
Названия
семейств формируются путем возведения
в множественное число названия
соответствующего объекта. В свою очередь
большинство объектов имеют присоединенные
коллекции свойств (Properties),
а формы и отчеты – коллекции разделов
и т.д. Так как все объекты в Access хранятся
внутри иерархически связанных коллекций,
то доступ к объекту на нижней ступени
иерархии можно получить, указав все
имена коллекций, разделенных точкой,
начиная от корневого объекта. Например,
Application.Forms(«Заказы»).Controls(0).Properties(0).
Большинство коллекций, к примеру,
коллекции форм и отчетов, являются
глобальными. Тогда к объекту этой
коллекции можно обращаться напрямую:
Forms(«Заказы») или Forms!Заказы.
Рис. 12. Иерархия
объектов Access
Поскольку
библиотека DAO всегда поставляется с
Access,
рассмотрим ее структуру и основные
методы более подробно (смотри Рис. 13).
Объекты
библиотеки DAO:
Database
– открытая база данных;
DBEngine
– ссылка на Microsoft Jet (ядро БД);
Error
– объект ошибок;
Field
– поле в таблицах, запросах, динамических
наборах и т.д.;
Index
– индекс;
Parameter
– параметр запроса;
QueryDef
– сохранённый запрос;
Recordset
– динамический набор данных;
Relation
– связь между таблицами;
TableDef
– сохраненная таблица;
Workspace
– активная сессия.
Рис. 13. Иерархия
объектов DAO
В
программах на VBA имеется набор свойств
объектов, которые возвращают ссылки на
подчиненные объекты:
Me
– ссылка на активную форму или отчет
(доступна в присоединенном модуле);
ActiveControl
– ссылка на активный элемент управления;
ActiveForm
– ссылка на активную форму (доступна в
объекте Screen);
ActiveReport
– ссылка на активный отчет (доступна в
объекте Screen);
Application
– ссылка на открытое приложение;
Parent
– ссылка на родительский объект, т.е.
на коллекцию;
DBEngine
–
возвращает
ссылку на Application.
Работа
с записями и полями
Применить
фильтрацию, изменить значение какого-либо
поля в базовом наборе данных либо даже
сменить базовый набор можно непосредственно
с помощью свойств самой формы и элементов
управления. Например:
Me![Полная
цена] = Me![Цена]
* Me![Количество]
Me.Filter
= «[Адрес] Like
‘*» & Me![ПолеУсловияПоиска]
& «*'»
Me.FilterOn
= True
Если
есть желание читать и менять данные в
некотором поле базового набора, но не
видеть его на экране, то достаточно
поместить элемент управления Поле
на форму и задать свойство Visible
в False.
Но прямой доступ к базовому набору в
Access
невозможен. Можно лишь создать динамическую
копию базового набора и синхронизировать
все производимые действия с ней с базовым
набором самой формы. Для прямого доступа
к записям и полям используется объект
Recordset. Имеются четыре типа Recordset объектов
– table,
dynaset,
snapshot
и forwarrd-only:
-
Table:
Может быть создан только на основе
существующей или присоединенной
таблицы. Предоставляет доступ ко всем
методам и свойствам таблицы, а также к
индексам, что дает намного более быстрый
метод поиска (метод Seek); -
Dynaset
— может быть создан на основе таблицы
или запроса. Позволяет обновлять данные
в многотабличных запросах и в запросах
к внешним БД. Обновление Dynaset
объекта приводит к автоматическому
обновлению всех участвующих в нем
таблиц; -
Snapshot
— создает статическую копию и существует
только в то время, когда он создан.
Последующие изменения таблиц на него
не воздействуют; -
Forward-only
создает статическую копию с просмотром
только в прямом порядке.
Для
создания объекта типа Recordset используется
метод OpenRecordset:
Set
variable = database.OpenRecodset (source [type, options, lockedits]),
или
Set
variable = object.OpenRecodset ( [type, options, lockedits]),
где
database – это
переменная
типа
Database; object – переменная
типа
TableDef или
QueryDef; source – ссылка
на
объект
типа
TableDef или
QueryDef; type – тип
динамического
набора
(может
принимать
следующие
значения:
dbOpenTable, dbOpenDynaset, dbOpenSnspshot dbOpenForwardOnly);
options может
принимать
следующие
значения:
dbAppendOnly, dbReadOnly, dbForwardOnly,
…; lockedits
– аргумент,
определяющий
разрешение
конфликтов
в
многопользовательских
БД
(может
принимать
следующие
значения:
DbReadOnly, dbPessimistic, dbOptimistic). Например:
Dim db As Database
Dim rst As Recordset
Set db = CurrentDb()
Set rst =
db.OpenRecordset(«Клиенты»,
dbOpenDynaset)
Открыть
Recordset можно и основываясь на переменной
типа формы (допустим только для форм,
основанных на таблице или запросе) с
помощью метода RecordsetClone. Метод RecordsetClone
создает динамический набор, основываясь
на свойстве Источник
данных для
формы
Dim
rstOrders As Recordset
Set
rstOrders = Forms![Заказы].RecordsetClone
или
просто Me.RecordsetClone
Recordset
можно создать, также основываясь на
строке SQL
Set rst =
db.OpenRecordset(«SELECT * FROM Товары
WHERE Цена
> 1000», dbOpenDynaset, dbReadOnly)
После
завершения работы с динамическим набором
его необходимо закрыть. Существуют два
общих способа закрытия объектов в VBA.
Первый заключается в вызове метода
Close, второй – в присвоении соответствующей
объектной переменной значения Nothing.
Например,
rst.Close или
Set rst = Nothing.
Recordset
имеет
текущее
приложение
– current position. Для
синхронизации текущего положения
динамического набора с текущей записью
формы можно использовать свойство
Bookmark
(необходимо всегда помнить, что при
обращении к динамическому набору данные
берутся именно из текущей записи). Для
перемещения по динамическому набору
имеется ряд методов: MoveFirst,
MoseLast,
MoveNext,
MovePrevions,
Move[n].
Например:
Dim
rst As Recordset
Set
rst = Me.RecordsetClone
rst.MoveNext
Me.Bookmark
= rst.Bookmark
Для
определения начала и конца набора можно
использовать свойства BOF (before of file –
начало файла) и EOF (end of file – конец файла).
Если в наборе нет записей, то BOF и EOF равны
True. Если в наборе есть записи, то при
открытии курсор обычно устанавливается
на первой записи и BOF и EOF = False. Если курсор
находится перед первой записью, то BOF =
True, и если курсор находится после
последней записи, то EOF = True.
Число
записей в динамическим наборе можно
получить с помощью свойства RecordCount. Это
свойство возвращает реальное число
записей только для динамического набора,
основанного на таблице, т.е. имеющего
тип dbOpenTable. После открытия динамических
наборов любых других типов число записей
в нем будет неизвестно до тех пор, пока
курсор не будет перемещен на последнюю
запись. Для непосредственной проверки
на наличие в наборе записей лучше
проверить свойство EOF. Если EOF будет
равно True, то RecordCount также будет равен 0.
Public
Function RecCount() As Long
Dim
rstCount As Recordset
Dim
dbs As Database
Set
dbs = CurrentDB()
Set
rstCont = dbs.OpenRecordset(«Заказы»)
If
rstCount.Eof Then
RecCount
= 0
Else
rstCount.MoveLast
RecCount
= rstCount.RecordCount
End
If
rstCount.Close
Set
dbs = Nothing
End
Function
Поиск
определенной записи
Для
наборов, основанных на таблице, можно
использовать метод Seek, который ищет
запись, основываясь на сравнении данных
некоторого индекса с заданными значениями
(самый быстрый метод). Для примера запишем
программу, которая будет проверять
дублирование значений ключевого поля
таблицы Клиенты
перед сохранением записи. Для проверки
результатов поиска в объекте Recordset
имеется свойство NoMatch. Если NoMatch равно
False, то запись с заданными условиями
поиска отсутствует в наборе.
Dim
rst As Recordset
Set
rst = CurrentDb.OpenRecordset(«Клиенты»,
dbOpenTable)
rst.Index
= «PrimaryКey»
rst.Seek
«=»,
Me![КодКлиента]
If
Not rst.NoMatch Then
MsgBox
«Клинт с таким табельным номером уже
существует в базе»
DoCmd.GoToControl
«КодКлиента»
End
If
rst.Close
Метод
Seek всегда начинает поиск с начала набора,
поэтому поиск по одному и тому же условию
будет всегда приводить к одной и той же
записи. Для поиска по динамическим
наборам остальных типов можно применять
также методы FindFirst, FindLast, FindNext и
FindPrevions. Например, подсчитаем количество
заказов определенного клиента:
intCount
= 0
rstOrders.FindFirst
«КодКлиента=» & Me![КодКлиента]
Do
While rstOrders.NoMatch
rstOrders.FindNext
«КодКлиента=»
& Me![КодКлиента]
intCount
= intCount + 1
Loop
Для
поиска записей можно также применять
сортировку и фильтрацию. Для сортировки
записей лучше всего открыть новый
динамический набор, основанный на
запросе SQL с оператором ORDER BY. Для
фильтрации можно задать свойство Filter
объекта Recordset и затем обновить набор с
помощью метода OpenRecordset.
Ниже приведен текст программы,
осуществляющей фильтрацию произвольного
набора:
Function
FilterField(rstTemp As Recordset, strField As String, strFilter As
String) As Recordset
rstTemp.Filter
= strField & » = ‘» & strFilter & «‘»
Set
FilterField = rstTemp.OpenRecordset
End
Function
Обновление
динамических наборов
Обновление
данных возможно только при работе с
динамическими наборами типов dbOpenTable и
dbOpenDynaset. Для редактирования некоторой
записи необходимо вначале установить
курсор на ней, перевести динамический
набор в режим редактирования (метод
Edit), а затем сохранить изменения с помощью
метода Update.
rst.Edit
rst![Товар]
= «Pentium
100»
rst![Цена]
= 100
rst.Update
Метод
Cancel
отменяет внесенные изменения. Для
удаления текущей записи существует
метод Delete. Этот метод удаляет запись
без выдачи каких-либо предупреждений
и не меняет положения курсора. Для
перехода на следующую запись необходимо
вызвать метод MoveNext. Для добавления новой
записи служит метод AddNew. После заполнения
новой записи значениями ее необходимо
сохранить с помощью метода Update, потому
как если после добавления новой записи
перейти к другой записи без сохранения
или просто закрыть динамический набор,
то добавляемая запись будет потеряна.
Следующий пример изменяет значения
полей Цена
и Количество
таблицы Заказы,
отфильтрованной для определенного
клиента.
Dim
rst As Recordset
Dim
dbs As Database
Set
dbs = CurrentDb()
Set
rst = dbs.OpenRecordset(«Заказы»,
dbOpenDynaset)
rst.Filter
= «[КодКлиента]=» & Me![Код
клиента]
Set
rst = rst.OpenRecordset
If
Not rst.EOF Then
With
rst
Do
Until .EOF
.Edit
![Цена]
= rst![Цена]
* 1.2
![Количество]
= ![Количество]
* 2
.Update
.MoveNext
Loop
.Close
End
With
End
If
dbs.Close
Работа
с
полями
Получить
доступ
к
значениям
и
свойствам
полей некоторой таблицы можно, открыв
соответствующий динамический набор.
Коллекция полей Fields является коллекцией
по умолчанию для объекта типа Recordset.
Тогда получить доступ к некоторому полю
можно по его имени или по индексу в
коллекции, например: rst.Fields(Field1”),
rst.Fields(4) или rst![Field1]. После получения
ссылки на объект типа Field можно читать
и изменять его свойства, например:
Dim
fld As Field
fld.DefaultValue
= 1
fld.ValidationRule
= «BETWEEN 1 AND 1000»
fld.Value
= 100
Соседние файлы в папке Лабораторный практикум в Access
- #
01.03.2016798.72 Кб118Articles2000.mdb
- #
01.03.2016311.3 Кб117Articles_be_2000.mdb
- #
- #
- #
- #
- #
- #
- #
03. В ADO и DAO ошибки обрабатываются по разному, используйте этот пример для анализа действий вашей программы при аварийных выходах.
Option Compare Database Option Explicit '*************************************************************** ' 03. Обработка ошибок разными методами '*************************************************************** '============================================================== ' ADO. Обработка ошибок Private Sub butADO_Click() Dim cnn As New ADODB.Connection Dim oneErr As ADODB.Error, s As String On Error Resume Next cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=?" ' Информация о всех ошибках s = "Список ошибок;------ ADO -------;" For Each oneErr In cnn.Errors s = s "Описание;" oneErr.Description ";" s = s "Номер;" oneErr.Number ";" s = s "Имя приложения;" oneErr.Source ";" s = s "SQLState;" oneErr.SQLState ";" s = s "NativeError;" oneErr.NativeError ";" s = s "Код справки;" oneErr.HelpContext ";" s = s "Файл справки;" oneErr.HelpFile ";" Next ' Полная информация о последней ошибке s = s "Последняя ошибка;------ ADO -------;" Me.listErrors.RowSource = s funLastError 'Отображаем ошибку Resume Next End Sub '============================================================== ' DAO. Обработка ошибок Private Sub butDAO_Click() Dim dbs As DAO.Database Dim oneErr As DAO.Error Dim strmdb As String, s As String On Error Resume Next Set dbs = DBEngine.OpenDatabase("?", , 2 / 0) ' Генерируем ошибку 'Err.Raise 11 ' Самостоятельный генератор ошибок ' Информация о всех ошибках s = "Список ошибок;------ DAO " DAO.Version " -------;" For Each oneErr In DBEngine.Errors s = s "Описание;" oneErr.Description ";" s = s "Номер;" oneErr.Number ";" s = s "Имя приложения;" oneErr.Source ";" Next ' Полная информация о последней ошибке s = s "Последняя ошибка;------ DAO -------;" Me.listErrors.RowSource = s funLastError 'Отображаем ошибку Err.Clear End Sub '============================================================== ' Возвращает информацию о последней ошибке ' ADO и DAO Private Function funLastError() As String Dim s As String s = "Описание;" Err.Description ";" s = s "Номер;" Err.Number ";" s = s "Код справки;" Err.HelpContext ";" s = s "Файл справки;" Err.HelpFile ";" s = s "Имя приложения;" Err.Source ";" s = s "DLL код;" Err.LastDllError ";" funLastError = s End Function
title | keywords | f1_keywords | ms.prod | ms.assetid | ms.date | ms.localizationpriority |
---|---|---|---|---|---|---|
Elements of run-time error handling |
vbaac10.chm5186924 |
vbaac10.chm5186924 |
access |
a0e06a1e-2709-aa51-92d0-340788a31a8a |
09/21/2018 |
medium |
Errors and error handling
When you are programming an application, you need to consider what happens when an error occurs. An error can occur in your application for one of two of reasons. First, some condition at the time the application is running makes otherwise valid code fail. For example, if your code attempts to open a table that the user has deleted, an error occurs. Second, your code may contain improper logic that prevents it from doing what you intended. For example, an error occurs if your code attempts to divide a value by zero.
If you’ve implemented no error handling, then Visual Basic halts execution and displays an error message when an error occurs in your code. The user of your application is likely to be confused and frustrated when this happens. You can forestall many problems by including thorough error-handling routines in your code to handle any error that may occur.
When adding error handling to a procedure, you should consider how the procedure will route execution when an error occurs. The first step in routing execution to an error handler is to enable an error handler by including some form of the On Error statement within the procedure. The On Error statement directs execution in event of an error. If there’s no On Error statement, Visual Basic simply halts execution and displays an error message when an error occurs.
When an error occurs in a procedure with an enabled error handler, Visual Basic doesn’t display the normal error message. Instead it routes execution to an error handler, if one exists. When execution passes to an enabled error handler, that error handler becomes active. Within the active error handler, you can determine the type of error that occurred and address it in the manner that you choose. Access provides three objects that contain information about errors that have occurred, the ADO Error object, the Visual Basic Err object, and the DAO Error object.
Routing execution when an error occurs
An error handler specifies what happens within a procedure when an error occurs. For example, you may want the procedure to end if a certain error occurs, or you may want to correct the condition that caused the error and resume execution. The On Error and Resume statements determine how execution proceeds in the event of an error.
On Error statement
The On Error statement enables or disables an error-handling routine. If an error-handling routine is enabled, execution passes to the error-handling routine when an error occurs.
There are three forms of the On Error statement: On Error GoTo label, On Error GoTo 0, and On Error Resume Next. The On Error GoTo label statement enables an error-handling routine, beginning with the line on which the statement is found. You should enable the error-handling routine before the first line at which an error could occur. When the error handler is active and an error occurs, execution passes to the line specified by the label argument.
The line specified by the label argument should be the beginning of the error-handling routine. For example, the following procedure specifies that if an error occurs, execution passes to the line labeled:
Function MayCauseAnError() ' Enable error handler. On Error GoTo Error_MayCauseAnError . ' Include code here that may generate error. . . Error_MayCauseAnError: . ' Include code here to handle error. . . End Function
The On Error GoTo 0 statement disables error handling within a procedure. It doesn’t specify line 0 as the start of the error-handling code, even if the procedure contains a line numbered 0. If there’s no On Error GoTo 0 statement in your code, the error handler is automatically disabled when the procedure has run completely. The On Error GoTo 0 statement resets the properties of the Err object, having the same effect as the Clear method of the Err object.
The On Error Resume Next statement ignores the line that causes an error and routes execution to the line following the line that caused the error. Execution isn’t interrupted. Use the On Error Resume Next statement if you want to check the properties of the Err object immediately after a line at which you anticipate an error will occur, and handle the error within the procedure rather than in an error handler.
Resume statement
The Resume statement directs execution back to the body of the procedure from within an error-handling routine. You can include a Resume statement within an error-handling routine if you want execution to continue at a particular point in a procedure. However, a Resume statement isn’t necessary; you can also end the procedure after the error-handling routine.
There are three forms of the Resume statement. The Resume or Resume 0 statement returns execution to the line at which the error occurred. The Resume Next statement returns execution to the line immediately following the line at which the error occurred. The Resume label statement returns execution to the line specified by the label argument. The label argument must indicate either a line label or a line number.
You typically use the Resume or Resume 0 statement when the user must make a correction. For example, if you prompt the user for the name of a table to open, and the user enters the name of a table that doesn’t exist, you can prompt the user again and resume execution with the statement that caused the error.
You use the Resume Next statement when your code corrects for the error within an error handler, and you want to continue execution without rerunning the line that caused the error. You use the Resume label statement when you want to continue execution at another point in the procedure, specified by the label argument. For example, you might want to resume execution at an exit routine, as described in the following section.
Exiting a procedure
When you include an error-handling routine in a procedure, you should also include an exit routine, so that the error-handling routine will run only if an error occurs. You can specify an exit routine with a line label in the same way that you specify an error-handling routine.
For example, you can add an exit routine to the example in the previous section. If an error doesn’t occur, the exit routine runs after the body of the procedure. If an error occurs, then execution passes to the exit routine after the code in the error-handling routine has run. The exit routine contains an Exit statement.
Function MayCauseAnError() ' Enable error handler. On Error GoTo Error_MayCauseAnError . ' Include code here that may generate error. . . Exit_MayCauseAnError: Exit Function Error_MayCauseAnError: . ' Include code to handle error. . . ' Resume execution with exit routine to exit function. Resume Exit_MayCauseAnError End Function
Handling errors in nested procedures
When an error occurs in a nested procedure that doesn’t have an enabled error handler, Visual Basic searches backward through the calls list for an enabled error handler in another procedure, rather than simply halting execution. This provides your code with an opportunity to correct the error within another procedure. For example, suppose Procedure A calls Procedure B, and Procedure B calls Procedure C. If an error occurs in Procedure C and there’s no enabled error handler, Visual Basic checks Procedure B, then Procedure A, for an enabled error handler. If one exists, execution passes to that error handler. If not, execution halts and an error message is displayed.
Visual Basic also searches backward through the calls list for an enabled error handler when an error occurs within an active error handler. You can force Visual Basic to search backward through the calls list by raising an error within an active error handler with the Raise method of the Err object. This is useful for handling errors that you don’t anticipate within an error handler. If an unanticipated error occurs, and you regenerate that error within the error handler, then execution passes back up the calls list to find another error handler, which may be set up to handle the error.
For example, suppose Procedure C has an enabled error handler, but the error handler doesn’t correct for the error that has occurred. Once the error handler has checked for all the errors that you’ve anticipated, it can regenerate the original error. Execution then passes back up the calls list to the error handler in Procedure B, if one exists, providing an opportunity for this error handler to correct the error. If no error handler exists in Procedure B, or if it fails to correct for the error and regenerates it again, then execution passes to the error handler in Procedure A, assuming one exists.
To illustrate this concept in another way, suppose that you have a nested procedure that includes error handling for a type mismatch error, an error which you’ve anticipated. At some point, a division-by-zero error, which you haven’t anticipated, occurs within Procedure C. If you’ve included a statement to regenerate the original error, then execution passes back up the calls list to another enabled error handler, if one exists. If you’ve corrected for a division-by-zero error in another procedure in the calls list, then the error will be corrected. If your code doesn’t regenerate the error, then the procedure continues to run without correcting the division-by-zero error. This in turn may cause other errors within the set of nested procedures.
In summary, Visual Basic searches back up the calls list for an enabled error handler if:
-
An error occurs in a procedure that doesn’t include an enabled error handler.
-
An error occurs within an active error handler. If you use the Raise method of the Err object to raise an error, you can force Visual Basic to search backward through the calls list for an enabled error handler.
Getting information about an error
After execution has passed to the error-handling routine, your code must determine which error has occurred and address it. Visual Basic and Access provide several language elements that you can use to get information about a specific error. Each is suited to different types of errors. Since errors can occur in different parts of your application, you need to determine which to use in your code based on what errors you expect.
The language elements available for error handling include:
-
Err object
-
ADO Error object and Errors collection
-
DAO Error object and Errors collection
-
AccessError method
-
Error event
Err object
The Err object is provided by Visual Basic. When a Visual Basic error occurs, information about that error is stored in the Err object. The Err object maintains information about only one error at a time. When a new error occurs, the Err object is updated to include information about that error instead.
To get information about a particular error, you can use the properties and methods of the Err object:
- The Number property is the default property of the Err object; it returns the identifying number of the error that occurred.
- The Err object’s Description property returns the descriptive string associated with a Visual Basic error.
- The Clear method clears the current error information from the Err object.
- The Raise method generates a specific error and populates the properties of the Err object with information about that error.
The following example shows how to use the Err object in a procedure that may cause a type mismatch error:
Function MayCauseAnError() ' Declare constant to represent likely error. Const conTypeMismatch As Integer = 13 On Error GoTo Error_MayCauseAnError . ' Include code here that may generate error. . . Exit_MayCauseAnError: Exit Function Error_MayCauseAnError: ' Check Err object properties. If Err = conTypeMismatch Then . ' Include code to handle error. . . Else ' Regenerate original error. Dim intErrNum As Integer intErrNum = Err Err.Clear Err.Raise intErrNum End If ' Resume execution with exit routine to exit function. Resume Exit_MayCauseAnError End Function
Note that in the preceding example, the Raise method is used to regenerate the original error. If an error other than a type mismatch error occurs, execution will be passed back up the calls list to another enabled error handler, if one exists.
The Err object provides you with all the information you need about Visual Basic errors. However, it doesn’t give you complete information about Access errors or Access database engine errors. Access and Data Access Objects (DAO)) provide additional language elements to assist you with those errors.
Error object and Errors collection
The Error object and Errors collection are provided by ADO and DAO. The Error object represents an ADO or DAO error. A single ADO or DAO operation may cause several errors, especially if you are performing DAO ODBC operations. Each error that occurs during a particular data access operation has an associated Error object. All the Error objects associated with a particular ADO or DAO operation are stored in the Errors collection, the lowest-level error being the first object in the collection and the highest-level error being the last object in the collection.
When a ADO or DAO error occurs, the Visual Basic Err object contains the error number for the first object in the Errors collection. To determine whether additional ADO or DAO errors have occurred, check the Errors collection. The values of the ADO Number or DAO Number properties and the ADO Description or DAO Description properties of the first Error object in the Errors collection should match the values of the Number and Description properties of the Visual Basic Err object.
AccessError method
Use the Raise method of the Err object to generate a Visual Basic error that hasn’t actually occurred and determine the descriptive string associated with that error. However, you can’t use the Raise method to generate a Access error, an ADO error, or a DAO error. To determine the descriptive string associated with an Access error, an ADO error, or a DAO error that hasn’t actually occurred, use the AccessError method.
Error event
Use the Error event to trap errors that occur on an Access form or report. For example, if a user tries to enter text in a field whose data type is Date/Time, the Error event occurs. If you add an Error event procedure to an Employees form, then try to enter a text value in the HireDate field, the Error event procedure runs.
The Error event procedure takes an integer argument, DataErr. When an Error event procedure runs, the DataErr argument contains the number of the Access error that occurred. Checking the value of the DataErr argument within the event procedure is the only way to determine the number of the error that occurred. The Err object isn’t populated with error information after the Error event occurs. Use the value of the DataErr argument together with the AccessError method to determine the number of the error and its descriptive string.
[!NOTE]
The Error statement and Error function are provided for backward compatibility only. When writing new code, use the Err and Error objects, the AccessError function, and the Error event for getting information about an error.
About the contributors
Link provided by the UtterAccess community.
- Handling Access Errors with VBA
UtterAccess is the premier Microsoft Access wiki and help forum.
See also
- Access for developers forum
- Access help on support.office.com
- Access forums on UtterAccess
- Access developer and VBA programming help center (FMS)
- Access posts on StackOverflow
[!includeSupport and feedback]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
Sub ImportExcel2() Dim strExcelPath As String, strTableName As String, strRangeName As String, strFile As String, IMPORT_FOLDER As String, n As Integer, strPathFile As String Dim IMPORT_FOLDER_DONE As String, strExcelPathDone As String, strPathFileDone As String, strFileNew As String IMPORT_FOLDER = "import" IMPORT_FOLDER_DONE = "importимпоритрованные" If Dir(CurrentProject.Path & "" & IMPORT_FOLDER, vbDirectory) = "" Then MkDir CurrentProject.Path & "" & IMPORT_FOLDER End If If Dir(CurrentProject.Path & "" & IMPORT_FOLDER_DONE, vbDirectory) = "" Then MkDir CurrentProject.Path & "" & IMPORT_FOLDER_DONE End If strExcelPath = CurrentProject.Path & "" & IMPORT_FOLDER strExcelPathDone = CurrentProject.Path & "" & IMPORT_FOLDER_DONE strTableName = "акты_импортированные_2" strRangeName = "Лист1!B4:D7" strFile = Dir(strExcelPath & "*.xlsm") n = 0 If strFile = Empty Then MsgBox "В папке:" & vbCr & strExcelPath & vbCr & "нет файлов для импорта" Else: Do While Len(strFile) > 0 strPathFile = strExcelPath & strFile strFileNew = "Импоритрован_" & strFile strPathFileDone = strExcelPathDone & strFileNew Call DoCmd.TransferSpreadsheet(acImport, _ acSpreadsheetTypeExcel12, strTableName, strPathFile, _ True, strRangeName) Name strPathFile As strPathFileDone 'Kill strPathFile strFile = Dir() n = n + 1 Loop MsgBox "Импортирован(о) " & n & " файл(ов)" End If End Sub Sub ImportExcel3() Dim strExcelPath As String, strTableName As String, strRangeName As String, strFile As String, IMPORT_FOLDER As String, n As Integer, strPathFile As String Dim IMPORT_FOLDER_DONE As String, strExcelPathDone As String, strPathFileDone As String, strFileNew As String IMPORT_FOLDER = "import" IMPORT_FOLDER_DONE = "importимпоритрованные" If Dir(CurrentProject.Path & "" & IMPORT_FOLDER, vbDirectory) = "" Then MkDir CurrentProject.Path & "" & IMPORT_FOLDER End If If Dir(CurrentProject.Path & "" & IMPORT_FOLDER_DONE, vbDirectory) = "" Then MkDir CurrentProject.Path & "" & IMPORT_FOLDER_DONE End If strExcelPath = CurrentProject.Path & "" & IMPORT_FOLDER strExcelPathDone = CurrentProject.Path & "" & IMPORT_FOLDER_DONE strFile = Dir(strExcelPath & "*.xlsm") n = 0 If strFile = Empty Then MsgBox "В папке:" & vbCr & strExcelPath & vbCr & "нет файлов для импорта" Else: Do While Len(strFile) > 0 strPathFile = strExcelPath & strFile strFileNew = "Импоритрован_" & strFile strPathFileDone = strExcelPathDone & strFileNew strTableName = "rekvizity" strRangeName = "rekvizity" Call DoCmd.TransferSpreadsheet(acImport, _ acSpreadsheetTypeExcel12, strTableName, strPathFile, _ True, strRangeName) strTableName = "obekty" strRangeName = "obekty" Call DoCmd.TransferSpreadsheet(acImport, _ acSpreadsheetTypeExcel12, strTableName, strPathFile, _ True, strRangeName) strTableName = "napravleniy" strRangeName = "napravleniy" Call DoCmd.TransferSpreadsheet(acImport, _ acSpreadsheetTypeExcel12, strTableName, strPathFile, _ True, strRangeName) strTableName = "meropriytiy" strRangeName = "meropriytiy" Call DoCmd.TransferSpreadsheet(acImport, _ acSpreadsheetTypeExcel12, strTableName, strPathFile, _ True, strRangeName) strTableName = "narusheniy" strRangeName = "narusheniy" Call DoCmd.TransferSpreadsheet(acImport, _ acSpreadsheetTypeExcel12, strTableName, strPathFile, _ True, strRangeName) Name strPathFile As strPathFileDone 'Kill strPathFile strFile = Dir() n = n + 1 Loop MsgBox "Импортирован(о) " & n & " файл(ов)" End If End Sub |