Примечание | А также лаб. работы: "Создание базы данных", "Создание запросов" |
Загрузить архив: | |
Файл: ref-25790.zip (1621kb [zip], Скачиваний: 135) скачать |
Лабораторная работа №6
Использование функций для обработки событий.
Обычно для обработки событий в формах и отчетах используют процедуры типа Sub (подпрограммы) или макросы. Однако иногда можно и даже нужно использовать функции. Дело в том, что если в рамках одной формы делается множество однотипных задач, то лучше создать одну процедуру — функцию для выполнения этих задач, описать ее на уровне модуля формы, т. е. в разделе General, а потом вызывать из любого места в форме. Если это необходимо, для такой функции определяется один или несколько параметров, которые передаются при вызове данной функции. И хотя значение, возвращаемое функцией, не используется (а обычно и не определяется), применение ее оправдано не только потому, что требуется писать меньше строк кода, а главным образом потому, что минимизация кода в модуле формы ускоряет ее
открытие.
Если же идентичные задачи решаются в разных формах, например, одна и та же реакция предусматривается для одинаковых кнопок в разных формах, то такую функцию нужно написать в стандартном модуле базы данных.
Скрытие и восстановление формы.
Функция для открытия формы:
Public Function OpenHide(strName As String)
Dim strHide As String
strHide = Screen.ActiveForm.Name
Screen.ActiveForm.Visible = False
DoCmd.OpenForm strName
Screen.ActiveForm.Tag = strHide
End Function
Screen- Объект объектной модели Microsoft Access 2002. Ссылается на конкретную форму, отчет или элемент управления, который в данный момент имеет фокус.
DoCmd - Объект объектной модели Microsoft Access 2002. Позволяет выполнить макрос или встроенную инструкцию Access с помощью процедуры на Visual Basic.
Visible – свойство вывода на экран. Может иметь значение True или False. В зависимости от его значения форма будет появляться или исчезать с экрана.
Tag – используемое при работе приложения свойство Дополнительные сведения (Tag). Позволяет сохранить произвольные дополнительные сведения о форме, отчете, странице доступа к данным и т. п. Представляет собой строковое значение длинной 2048 символов. Данное свойство позволяет определить для объекта кодовую строку без возникновения каких-либо побочных эффектов.
Функция для закрытия формы
Public Function Close Unhide ()
Dim strUnhide 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 в программе Visual Basic следует использовать метод SelectObject объекта DoCmd.
Рассмотрим работу этих функций на примере БД Northwind и ее форм – Products и Categories. Реализуем возможность открытия формы Categories из формы Products.Для работы этих процедур выполняются следующие действия.
1.Добавить функции в новыймодуль.
2.Открыть форму Products (Товары) в режиме конструктора. В разделе примечания формы добавить кнопку cmdOpenHide и установить свойство Caption (Подпись) равным «Открыть Categories». Выберать в свойствах кнопки событие «Нажатие кнопки» (OnClick) и установить = OpenHide(“Categories”)
3.Открыть форму Categories (Категории) в режиме конструктора. В разделе примечания формы добавить кнопку cmdCloseUnhide и установить свойство Caption (Подпись) равным «Закрыть форму». Выбрать в свойствах кнопки событие «Нажатие кнопки» (OnClick) и установить = CloseUnhide()
Реализовать возможность открытия формы (Участники) из другой формы (Мероприятия). Вторая форма должна хранить информацию о том, из какой формы она была открыта, чтобы после закрытия восстановить на экране именно эту форму. Для этой цели используем свойство, зарезервированное для пользователей Tag.
Проверьте работу:
Откройте форму Мероприятия. Нажмите кнопку «Открытие Участников». Текущая форма исчезнет с экрана и откроется форма Участники. Нажмите кнопку «Закрыть форму», снова появится формаМероприятия.
Синхронизация двух форм
Рассмотрим пример – создадим процедуру обработки события, которая будет открывать форму Customers из формы Orders и синхронизировать ее с формой Orders. Для работы этих процедур выполняются следующие действия.
1.Открытие формы Orders в режиме конструктора, добавление кнопки cmdViewCustomer с подписью «Сведения о покупателе» («ViewCustomer»). Для события «Нажатие кнопки» (OnClick) вводится процедура:
Private Sub cmdViewCustomer_Click()
Dim strForm As String
Dim strWhere As 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 strForm As String
Dim strWhere As String
strForm = "Customers"
strWhere = "CustomerID = Forms!Orders!CustomerID"
If IsLoaded(strForm) Then
DoCmd.OpenForm FormName:=strForm, wherecondition:=strWhere
End If
End Sub
Function IsLoaded (ByVal strFormName As String) As Boolean
Const conObjStateClosed = 0
Const conDesignView = 0
If SysCmd (acSysCmdGetObjectState, acForm, strFormName) <>
ConObjStateClosed
Then
If Forms(strFormName).CurrentView <> conDesignView Then
IsLoaded = True
End If
End If
End Function
4.При закрытии формы Orders необходимо закрыть форму Customers (если она открыта). Процедура обработки события Close в форме Orders, закрывает форму Customers, если она открыта.
Private Sub Form_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![form name],Forms("formname")
Свойство CurrentViewпринимает следующие значения.
0 |
Режим конструктора |
1 |
Режим формы |
2 |
Список БД |
Метод VisualBasicMoveSize изменяет положение или размеры активного окна. Его можно использовать для удобного с точки зрения пользователя расположения синхронизированных форм.
DoCmd.MoveSize 1440, 2400, , 2000
DoCmd.MoveSize (Right, Down, Width, Height)
Right– новое положение верхнего левого угла окна (по горизонтали) относительно левого края содержащего его окна.
Down–новое положение верхнего левого угла окна (по вертикали) относительно верхнего края содержащего его окна
Width– новая ширина окна.
Height– новая высота окна.
Создать процедуру обработки события, которая будет открывать форму Организаторы, и синхронизировать ее с формой Мероприятия. Закрытие формы Организаторы должно вызывать закрытие и формы Мероприятия.
Выполнение операций с записями.
Семейство 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 <имяМассива> (<размер1>[, <размер2>] . . . )
Более того, можно неоднократно использовать оператор ReDim для изменения размерности оного и того же массива. Однако, так как при изменении размерности массива для него заново выделяется память, то текущие значения его элементов теряются. Чтобы их сохранить при перераспределении размерности, используется ключевое слово Preserve. В этом случае можно поменять только последний аргумент, задающий размерность массива.
‘…………………………………………………………………..
Private SubcmdFind_Click()
Dim str As String
Dim db As Database
Dim rs As DAO.Recordset
Dim i As Integer
Set db = CurrentDb
Set rs = db.OpenRecordset("Вакансии ", dbOpenSnapshot)
‘……………………………………………………………………
If rs.RecordCount = 0 Then
MsgBox "Вакансии отсутствуют"
Exit Sub
End If
‘Поиск – имя формы, а txtWho – имя поля для ввода вакансии
str = "Должность ='" & Forms!Поиск!txtWho & "'"
rs.FindFirst str
If rs.NoMatch Then
MsgBox "Вакансии отсутствуют"
Exit Sub
Else
ReDim Preserve IdList(i)
IdList(i) = rs!Код
…………………………………………………………………
Do Until rs.EOF
rs.FindNext str
If rs.NoMatch = False Then
i = i + 1
ReDim Preserve IdList(i)
‘Кодобработкиданных
IdList(i) = rs! Код
…………………………………………………………………
End If
rs.MoveNext
End If
rs.Close
db.Close
End Sub
Усовершенствуемформу РезультатыПоиска, добавив возможность просмотра списка сотрудников по вводимым должностям. Рис. 1
Добавить на форму кнопку с надписью Поиск по должностям и список для вывода сотрудников. Нажатие кнопки приводит к поиску соответствующих записей и отображению в списке табельных номеров и фамилий сотрудников.
Применение метода Seek.
Метод Seek используется для объекта Recordsetтабличного типа. Он выполняет поиск нужной записи с использованием индекса. Поэтому перед выполнением поиска нужно указать существующий индекс, который нужно использовать (текущий индекс).
Синтаксис метода для объектной моделиDAO:
Таблица.Seek сравнение, ключ1, ключ2, … ключn
= | >| < |>= | <= |
Аргументы ключ – те значения, которые нужно найти. Количество аргументов определяется количеством полей в индексе и совпадает с порядком в нем. Данный метод позволяет найти только первую запись, удовлетворяющую заданному критерию, даже если их несколько. Поэтому его используют для быстрого поиска записи по ключу.
В примере представлена процедура, которая ищет данные о заказе по его номеру.
Private Sub cmdFind1_Click()_Click()
Dim db As Database
Dim StrFilter As String
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("Заказы", dbOpenTable)
rs.Index = "PrimaryKey"
rs.Seek "=", Me!txtOderID
If rs.NoMatch Then
MsgBox "Нет заказа с таким номером"
Exit Sub
Else
‘Код обработки данных о найденном заказе
End If
rs.Close
db.Close
End Sub
Усовершенствуемформу РезультатыПоиска, добавив возможность быстрого поиска сотрудника в таблице “Личныеданные” по его регистрационному номеру. В подчиненной форме должна отображаться только запись с данными о найденном лице либо выдаваться сообщение об отсутствии такого номера в базе.
Изменение данныхв объекте Recordset.
Изменяемым может быть только динамический набор записей и таблица.
Для объектной модели DAOпри добавлении записи необходимо:
Private Sub New_Click()
Dim rs As DAO.Recordset, dbCur As Database
Set dbCur = CurrentDb
Set rs = dbCur.OpenRecordset("Кадры", dbOpenDynaset)
rs.AddNew
rs!ТабельныйНомер = txtNome
rs!КодПодразделения = txtNumber
rs!Пол = cmbSex.Column(0)
‘………………………………………….................................
rs.Update
rs.Close
dbCur.Close
End Sub
Изменение существующей записи.
Для объектной модели DAOизменения текущей записи выполняются следующим образом:
Private Sub Editrec_Click()
Dim rs As DAO.Recordset, dbCur As Database
Set dbCur = CurrentDb
Set rs = dbCur.OpenRecordset("Штатное расписание")
rs.MoveFirst
Do Until rs.EOF
If rs!КодПодразделения = CInt(Me!txtNumber) Then
rs.Edit
‘Задание новых значений для полей редактируемой записи
‘………………………………………….......................
rs.Update
End If
rs.MoveNext
rs.Close
dbCur.Close
End Sub
Удаление существующей записи.
Для удаления записи внаборе нужно сделать эту запись текущей и затем вызвать метод Delete. Запись без предупреждения удаляется из таблицы, автоматического перехода к новой записи не происходит.
‘………………………………………….......
Do Until rs.EOF
If rs! КодПодразделения = CInt(Me!txtNumber) Then
rs.Delete
End If
rs.MoveNext
‘…………………………………………........
Примечание:CInt(аргумент) – функция преобразования типа. Возвращаемый тип – Integer.
Создатьформу Работасзапиями.
Реализовать процедуры, выполняющие соответственно добавление нового сотрудника в таблицу “Личныеданные”, редактирование данных существующего сотрудника(он определяется по регистрационному номеру), удаление существующей записи. При удалении организовать вывод сообщения, информирующего пользователя об удалении. В случае подтверждения намерений удалить запись – она удаляется, а в противном случае – нет.