Access for Microsoft 365 Access 2021 Access 2019 Access 2016 Access 2013 Access 2010 Access 2007 More…Less
Returns a Boolean value indicating whether an expression> is an error value.
Syntax
IsError
(
expression
)
The required expressionargument can be any valid expression.
Remarks
Error values are created by converting real numbers to error values using the CVErr function. The IsError function is used to determine if a numeric expression represents an error. IsError returns True if the expression argument indicates an error; otherwise, it returns False.
Example
Note: Examples that follow demonstrate the use of this function in a Visual Basic for Applications (VBA) module. For more information about working with VBA, select Developer Reference in the drop-down list next to Search and enter one or more terms in the search box.
This example uses the IsError function to check if a numeric expression is an error value. The CVErr function is used to return an Error Variant from a user-defined function. Assume UserFunction is a user-defined function procedure that returns an error value; for example, a return value assigned with the statement UserFunction = CVErr(32767), where 32767 is a user-defined number.
Dim ReturnVal, MyCheck
ReturnVal = UserFunction()
MyCheck = IsError(ReturnVal) ' Returns True.
Need more help?
Want more options?
Explore subscription benefits, browse training courses, learn how to secure your device, and more.
Communities help you ask and answer questions, give feedback, and hear from experts with rich knowledge.
-
Обработка ошибок на этапе выполнения
Как
тщательно не проверялся бы код, на этапе
его выполнения неизбежно возникают
ошибки. Попытка деления на ноль – это
типичный пример ошибки времени выполнения.
В 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
- #
- #
- #
- #
- #
- #
- #
I am working on a Attendance table in Access, where I have InTime
and OutTime
. These fields are of Date/Time Field.
Some records contains only Time like 11:40:00
, some contain Date as well as time like 21-07-2015 11:45:00
. Hence have used the below code for getting hours worked.
HrsPresent: Round(DateDiff("n",TimeValue(TimeSerial(Hour([TimeIn]),Minute([TimeIn]),Second([TimeIn]))),TimeValue(TimeSerial(Hour([TimeOut]),Minute([TimeOut]),Second([TimeOut]))))/60,2)
Using this above code, in a Column in making query gives correct Number of hours worked, but if any of the field is blank, i get #error
in result.
I have tried using Nz
, IsError
, IsNumeric
but all in Vain.
- What is it that, I am doing wrong?
- Is other way of getting hours worked?
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
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 |