Лабораторная работа №6
Использование функций для обработки событий.
Обычно для обработки событий в формах и отчетах используютпроцедуры типа Sub (подпрограммы) или макросы. Однако иногда можно и даженужно использовать функции. Дело в том, что если в рамках одной формы делаетсямножество однотипных задач, то лучше создать одну процедуру — функцию длявыполнения этих задач, описать ее на уровне модуля формы, т. е. в разделе General,а потом вызывать из любого места в форме. Если это необходимо, для такойфункции определяется один или несколько параметров, которые передаются привызове данной функции. И хотя значение, возвращаемое функцией, не используется(а обычно и не определяется), применение ее оправдано не только потому, чтотребуется писать меньше строк кода, а главным образом потому, что минимизациякода в модуле формы ускоряет ее
открытие.
Если же идентичные задачи решаются в разных формах,например, одна и та же реакция предусматривается для одинаковых кнопок в разныхформах, то такую функцию нужно написать в стандартном модуле базы данных.
Скрытие и восстановление формы.
Функциядля открытия формы:
Public Function OpenHide(strName As String)
Dim strHideAs String
strHide =Screen.ActiveForm.Name
Screen.ActiveForm.Visible = False
DoCmd.OpenForm strName
Screen.ActiveForm.Tag = strHide
End Function
Screen — Объект объектной модели Microsoft Access2002. Ссылается на конкретную форму, отчет или элемент управления, который в данный момент имеет фокус.
DoCmd — Объект объектной моделиMicrosoft Access 2002. Позволяет выполнить макрос или встроенную инструкциюAccess с помощью процедуры на Visual Basic.
Visible – свойство вывода на экран.Может иметь значение True или False. В зависимости от его значения форма будетпоявляться или исчезать с экрана.
Tag– используемое при работе приложения свойство Дополнительные сведения (Tag).Позволяет сохранить произвольные дополнительные сведения о форме,отчете,страницедоступа к данным и т. п. Представляет собой строковое значениедлинной 2048 символов. Данное свойство позволяет определить для объекта кодовуюстроку без возникновения каких-либо побочных эффектов.
Функция для закрытия формы
Public Function Close Unhide ()
DimstrUnhide As String
If IsNull(Screen.ActiveForm.Tag) Then
DoCmd.Close
Else
strUnhide = Screen.ActiveForm.Tag
DoCmd.Close
DoCmd.SelectObject acForm, strUnhide
End If
End Function
Макрокоманда «ВыделитьОбъект» (SelectObject)выделяет указанный объект базыданных (в качестве аргументов необходимо указать тип объекта,который будет выбран и имя выбираемого объекта). Макрокоманда SelectObjectприменима к любому объекту Access, которому можно передать фокус.Эта макрокоманда переводит фокус на указанный объект и, если объект в данныймомент скрыт, выводит его на экран. Для формымакрокоманда SelectObject автоматически устанавливает значение Дасвойства Вывод на экран (Visible) и восстанавливает режим окна формы,указанный в свойствахформы (например, режим модальнойили всплывающейформы). Для запуска макрокоманды SelectObject в программе VisualBasic следует использовать метод SelectObject объекта DoCmd.
Рассмотрим работу этих функций на примереБД Northwind и ее форм – Products и Categories. Реализуем возможность открытияформы Categories из формы Products. Дляработы этих процедур выполняются следующие действия.
1. Добавить функции вновый модуль.
2. Открыть форму Products(Товары) в режиме конструктора. В разделе примечания формы добавить кнопку cmdOpenHideи установить свойство Caption(Подпись) равным «Открыть Categories».Выберать в свойствах кнопки событие «Нажатие кнопки» (OnClick) и установить = OpenHide(“Categories”)
3. Открыть форму Categories(Категории) в режиме конструктора. В разделе примечания формы добавить кнопку cmdCloseUnhideи установить свойство Caption(Подпись) равным «Закрытьформу». Выбрать в свойствах кнопки событие «Нажатие кнопки» (OnClick)и установить = CloseUnhide()Задание №1
Реализовать возможностьоткрытия формы (Участники) из другойформы (Мероприятия). Вторая формадолжна хранить информацию о том, из какой формы она была открыта, чтобы послезакрытия восстановить на экране именно эту форму. Для этой цели используемсвойство, зарезервированное для пользователей Tag.
Проверьте работу:
Откройте форму Мероприятия. Нажмите кнопку «Открытие Участников». Текущая форма исчезнет с экрана и откроется форма Участники. Нажмите кнопку «Закрыть форму», снова появитсяформа Мероприятия.
Синхронизация двух форм
Рассмотрим пример – создадим процедуру обработкисобытия, которая будет открывать форму Customersиз формы Ordersисинхронизировать ее с формой Orders. Для работы этих процедурвыполняются следующие действия.
1. Открытие формы Ordersврежиме конструктора, добавление кнопки cmdViewCustomerс подписью «Сведения опокупателе» («ViewCustomer»). Для события «Нажатиекнопки» (OnClick) вводится процедура:
Private Sub cmdViewCustomer_Click()
Dim strFormAs String
Dim strWhereAs String
strForm =«Customers»
strWhere =«CustomerID = Forms!Orders!CustomerID»
DoCmd.OpenForm FormName:=strForm, wherecondition:=strWhere
End Sub
2. Если открыть форму Ordersинажать кнопку «Сведения о покупателе», то откроется форма Customers, в которой выводятсясведения о данном покупателе. При выборена форме Ordersзаказа другого клиента форма Customersне обновляется до тех пор, пока повторно не будет нажата кнопка «Сведения опокупателе».
3. Для реализации механизмасинхронизации форм необходимо создать процедуру обработки события длясинхронизации формы Customersпри смене записи в форме Orders. При переходе к другойзаписи используется событие Current«Текущая запись» формы Customers.Для определения, открыта ли форма Customers, процедура обработкисобытия Form_Currentдля формы Ordersиспользует функцию пользователя IsLoaded()
Private Sub Form_Current()
Dim strFormAs String
Dim strWhereAs String
strForm =«Customers»
strWhere =«CustomerID = Forms!Orders!CustomerID»
IfIsLoaded(strForm) Then
DoCmd.OpenForm FormName:=strForm, wherecondition:=strWhere
End If
End Sub
Function IsLoaded (ByVal strFormName As String) AsBoolean
ConstconObjStateClosed = 0
ConstconDesignView = 0
If SysCmd(acSysCmdGetObjectState, acForm, strFormName)
ConObjStateClosed
Then
IfForms(strFormName).CurrentView conDesignView Then
IsLoaded = True
End If
End If
End Function
4. При закрытии формы Ordersнеобходимо закрыть форму Customers(если она открыта).Процедура обработки события Closeв форме Orders,закрывает форму Customers, если она открыта.
Private SubForm_Close()
Dim strForm As String
strForm = «Customers»
DoCmd.Close acForm, strForm
End Sub
Метод SysCmdможет возвращать сведения осостоянии объекта БД (не открыт или не существует, открыт, новый, изменен, ноне сохранен). Вызывая SysCmd метод с аргументами acSysCmdGetObjectState,objecttype(acТable,acQuery,acForm, acReport и т. п.) и objectname, мы получим информацию осостоянии определенного объекта БД (по указанному имени объекта).
Метод SysCmdс аргументом acSysCmdGetObjectStateможет возвращать только следующие константы.
Константа
Состояние объекта
Значение
acObjStateOpen
Открыт
1
acObjStateDirty
Изменен, но не сохранен
2
acObjStateNew
Новый
4
Если объект не открыт или не существует,метод SysCmdвозвращает значение 0.
Свойство CurrentView применительнок объектам формы определяет ее вид представления в текущий момент и возвращаетчисло типа Integer.
expression.CurrentView
expression применительно к формам может быть: Forms!formname,
Forms![formname], Forms(«formname»)
Свойство CurrentView принимает следующие значения.
Режим конструктора
1
Режим формы
2
Список БД
Метод VisualBasicMoveSize изменяет положение илиразмеры активного окна. Его можно использовать для удобного с точки зренияпользователя расположения синхронизированных форм.DoCmd.MoveSize 1440, 2400,, 2000
DoCmd.MoveSize(Right, Down, Width, Height)
Right–новое положение верхнего левого угла окна (по горизонтали) относительно левогокрая содержащего его окна.
Down – новое положениеверхнего левого угла окна (по вертикали) относительно верхнего края содержащегоего окна
Width – новая ширина окна.
Height– новая высота окна.Задание №2
Создать процедуру обработкисобытия, которая будет открывать форму Организаторы,и синхронизировать ее с формой Мероприятия.Закрытие формы Организаторы должновызывать закрытие и формы Мероприятия.
Выполнение операций с записями.
Семейство Recordsets.
Объекты Recordset представляют собойнаборы записей, являющихся результатом выполнения запроса или инструкции SQLнавыборку данных, или просто все записи в таблице. Новый объект Recordset создаетсяс помощью метода OpenRecordset объекта Database иавтоматически добавляется в семейство Recordsets.
Существует 5 типов объектов Recordset:
Таблица1
Тип
Константа
Описание
Таблица
dbOpenTable
Этот тип может быть создан только на основе локальной таблицы ACCESS. Он содержит все записи этой таблицы. Можно изменять данные в этом объекте и добавлять и удалять записи.
Статистический набор записей
dbOpenSnapshot
Набор записей, создаваемый на основе таблицы, запроса или инструкции SQL. Обеспечивает только просмотр данных без его модификации.
Динамический набор записей
dbOpenDynaset
Набор записей, создаваемый на основе таблицы, запроса или инструкции SQL. Однако он является изменяемым и обновляемым.
Статический набор записей с последовательным доступом
dbOpenForwardOnly
Аналогичен статистическому набору записей во всем, кроме того, что он позволяет просматривать записи набора только вперед, т. е. один раз.
Динамический
dbOpenDynamic
Похож на динамический. Отличие заключается в том, что он отображает все изменения, сделанные другим пользователем, после того, как этот объект был создан, в том числе добавленные и удаленные записи.
Чтобы создать объектRecordset,нужно сначала создать объектную переменную. После этого выполняетсяприсвоение значений этой переменной с помощью метода OpenRecordset.Метод имеет аргументы:
Источник данных для данного набора записей (таблица, запрос).
Тип создаваемого объекта (одна из констант из Таблицы1).
Комбинация констант, которые определяют некоторые характеристикисоздаваемого объекта.
Тип блокировки
Объект Recordset используется дляработы с записями и с полями в записях. Свойство Count семействауказывает количество полей в наборе записей. Семейство Fieldsявляется стандартным семейством объекта Recordset, поэтому возможна короткая ссылка rs! Имя (где переменная rsобъявлена, например как, DimrsAsDAO.Recordset).
После окончания работы с набором записей необходимовыполнить метод Close объекта Recordset, чтобыудалить набор из памяти.
Рассмотрим выполнение операций над записями спомощью свойств и методов объекта Recordset и Field,которые имеются в объектных моделях DAOи ADO.
Рассмотрим объектную модель DAO.
Синтаксис создания объекта Recordset:
СсылкаНаОбъект_Database_или_Connection.OpenRecordset (источник, [типОбъекта]. [параметры], [типБлокировки]
Значениеаргумента параметры метода OpenRecordset:
Константа
Описание
dbAppendOnly
Разрешено только добавление записей в объект Recordset.
Применяется только для динамического набора записей.
dbSQLPassThrough
Результирующий набор – статический. Используется для выполнения прямого запроса к серверу, когда в качестве аргумента Источник указывается сам запрос.
dbSeeChanges
Применяется только для динамического набора и не разрешает изменять запись, если она уже редактируется другим пользователем
dbDenyWrite
Запрещено другим пользователям изменять и добавлять записи в наборе.
dbDenyRead
Запрещено другим пользователям изменять и добавлять записи и читать данные из таблицы (применяется только к объекту Recordset типа таблица).
dbForwardOnly
Дублирует константу acOpenForwardOnlyдля аргумента тип объекта.
dbReadOnly
Данные в наборе будут доступны только для чтения.
dbRunAsync
Выполняет асинхронный запрос.
dbExecDirect
Выполнение ускорения запроса.
dbInconsistent
Разрешены несогласованные изменения.
dbConsistent
Разрешены только согласованные обновления записей.
Значение аргумента тип блокировки неприводится, т. к. в данной работе он не используется.
Перемещение по набору записей.
Для получения значений полей произвольной записинабора, сначала надо сделать требуемую запись текущей, т. е. переместиться наэту запись. Для перемещения по набору записей используются методы:
MoveFirst – переход к первой записи набора. Прииспользовании статистического курсора с последовательным доступом вызываетповторное выполнение команды, которая возвратила Recordset. Используетсяпри всех типах курсоров.
MoveNext – переход к следующей записи. Используется привсех типах курсоров.
MovePrevious – переход к предыдущей записи. При использованиистатического курсора с последовательным доступом вызывает генерацию ошибкивремени исполнения.
MoveLast –переход к последней записи. Прииспользовании статического курсора с последовательным доступом вызываетгенерацию ошибки времени исполнения.
Move – позволяет переместиться на заданное числозаписей вперед или назад. При использовании статического курсора споследовательным доступом вызывает генерацию ошибки времени исполнения.
При перемещении по набору записей необходимо контролировать, чтобы непереместить указатель за границы набора. Используются два свойства:
BOF – принимает значение TRUE, как только указательтекущей записи оказывается перед первой записью набора.
EOF – принимает значение TRUE, кактолько указатель текущей записи оказывается после последней записи набора илиесли в наборе нет ни одной записи.
Организация цикла по набору записей:
Вариант 1
Dim rs As DAO.Recordset
Dim dbCur As Database
‘……………………………….
‘Используется для заполненияисточника строк поля со списком формы
Set dbCur=CurrentDb
Set rs=dbCur.OpenRecordset («Select Код, НазваниеFROM Образование „_
& «ORDER BY Название», dbOpenSnapshot)
rs.MoveFirst
While Not rs.EOF
CmdEducation.RowSource= CmdEducation.RowSource &rs! Код & “;” &_
rs! Название & “;”
rs.MoveNext
Wend
rs.Close
dbCur.Close
Вариант 2
Dim rs As DAO.Recordset
Dim dbCur As Database, i as integer
‘……………………………….
Set dbCur=CurrentDb
Set rs=dbCur.OpenRecordset («Кадры », dbOpenDynaset)
If rs.RecordCount 0 Then
rs.MoveFirst
For i=1 to rs.RecordCount
‘ Код обработки записи
rs.MoveNext
Next I
End IF
rs.Close
dbCu.Close
Во втором варианте использовано свойство RecordCount.Для набора записей типа Таблицаэто свойство возвращает общее количество записей в наборе. Для набора записейстатического или динамического типа, значение этого свойства равно 1. Этопроисходит потому, что не все записи сразу считываются с источника, однакопредполагается, что набор содержит хотя бы одну запись. Чтобы узнать общеечисло записей в подобных наборах, нужно перейти в конец набора с помощью метода Movelast (при этом все записи будутпрочитаны). Теперь свойство RecordCount будет содержать нужноезначение.
Иногда требуется определить позицию текущей записи внаборе. Свойство AbsolutePositionвозвращает абсолютнуюпозицию текущей записи (от 1 до RecordCount),а свойство PercentPosition– относительную позициютекущей записи в процентах от числа записей, которое отражается в свойстве RecordCount(поскольку свойство RecordCount не всегда совпадает собщим числом записей в наборе, то рассматриваемое свойство не всегда возвращаетверное число).
Поиск записей в объекте Recordset.
Методы поиска записей в наборе зависят от типанабора записей. Для объектов Recordset типа Таблица используется метод Seek, а для статическогоили динамического наборов – группа методов Find. Для DAOдлястатического набора с последовательным доступом поиск не поддерживается вообще.
Seek использует индексы таблицы, на основе которойсоздан объект Recordset (в DAOего можно использовать толькодля объектов Recordset типа Таблица).Если поиск не был успешным, то в модели DAOтекущая запись неопределена.
Применение методов Find.
ДляDAOопределены:
FindFirst – ищется первая запись, удовлетворяющаязаданным условиям.
FindLast – ищется последняя запись, удовлетворяющаязаданным условиям.
FindNext – ищется следующая запись, удовлетворяющаязаданным условиям.
FindPrevious – ищется предыдущая запись, удовлетворяющаязаданным условиям.
Каждый из этих методов имеет один аргумент, задающийусловия поиска (строится по правилам опции Whereв инструкции SQL).Результат поиска отображается в значении свойства NoMatchобъекта Recordset. При успешном поискеNoMatchимеет значение FALSE, а при неудаче – TRUE.
Каждый из методов Findначинает поиск сразных точек в разных направлениях.
FindFirst – начинает работу с начала набора и к концу.
FindLast – с конца к началу.
FindNext – от текущей записи и к концу.
FindPrevious– от текущей записи и к началу.
Примечание:
В VBA допускается использование и динамическихмассивов, размеры которых при описании не фиксируются. Определение размера динамическогомассива может быть сделано непосредственно во время выполнения программы. Приопределении динамического массива в операторе Dim после имени массива стоятлишь пустые скобки и описание типа переменных. Количество индексов и диапазоних изменения не задаются. Однако перед тем, как использовать массив, нужновыполнить оператор ReDim, который задаст размерность и диапазоны измененияиндексов динамического массива.
Синтаксис объявления и определения размеровдинамического массива таков:
Dim ( ) As
ReDim ([,]… )
Более того, можно неоднократно использовать операторReDimдля изменения размерности оного и того же массива. Однако, так как приизменении размерности массива для него заново выделяется память, то текущиезначения его элементов теряются. Чтобы их сохранить при перераспределенииразмерности, используется ключевое слово Preserve. В этом случае можно поменятьтолько последний аргумент, задающий размерность массива.
‘…………………………………………………………………..
PrivateSub cmdFind_Click()
Dim str AsString
Dim db AsDatabase
Dim rs AsDAO.Recordset
Dim i AsInteger
Set db =CurrentDb
Set rs =db.OpenRecordset(“Вакансии “, dbOpenSnapshot)
‘……………………………………………………………………
Ifrs.RecordCount = 0 Then
MsgBox«Вакансии отсутствуют»
Exit Sub