Использование функций для обработки событий

ПримечаниеА также лаб. работы: "Создание базы данных", "Создание запросов"
Загрузить архив:
Файл: 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()

Задание №1

Реализовать возможность открытия формы (Участники) из другой формы (Мероприятия). Вторая форма должна хранить информацию о том, из какой формы она была открыта, чтобы после закрытия восстановить на экране именно эту форму. Для этой цели используем свойство, зарезервированное для пользователей 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– новая высота окна.

Задание №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 <имяМассива> (<размер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

Loop

End If

rs.Close

db.Close

End Sub

Задание №3

Усовершенствуемформу РезультатыПоиска, добавив возможность просмотра списка сотрудников по  вводимым должностям. Рис. 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          

Задание №4

Усовершенствуемформу РезультатыПоиска, добавив возможность быстрого поиска сотрудника в таблице “Личныеданные” по его регистрационному номеру. В подчиненной форме должна отображаться только запись с данными о найденном лице либо выдаваться сообщение об отсутствии такого номера в базе.

                                                  

Изменение данныхв объекте Recordset.

Изменяемым может быть только динамический набор записей и таблица.

Для объектной модели DAOпри добавлении записи необходимо:

  1. Выполнить метод AddNew, чтобы создать новую пустую запись и сделать ее текущей.
  2. Присвоить значения всем обязательным полям записи.
  3. Выполнить метод Update, чтобы сохранить внесенные изменения. Указатель текущей записи при этом снова перемещается на ту запись, на которой был установлен до применения метода AddNew.

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изменения текущей записи выполняются следующим образом:

  1. Вызывается метод Edit, который переводит запись в состояние изменения.
  2. Вносятся изменения в поля записи.
  3. Выполнить метод Update для сохранения внесенных изменений.

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

Loop

rs.Close

dbCur.Close

End Sub

Удаление существующей записи.

Для удаления записи внаборе нужно сделать эту запись текущей и затем вызвать метод Delete. Запись без предупреждения удаляется из таблицы, автоматического перехода к новой записи не происходит.

‘………………………………………….......

Do Until rs.EOF

If rs! КодПодразделения = CInt(Me!txtNumber) Then

rs.Delete

End If

rs.MoveNext

Loop

‘…………………………………………........

Примечание:CInt(аргумент) – функция преобразования типа. Возвращаемый тип – Integer.

Задание №5

Создатьформу Работасзапиями.

Реализовать процедуры, выполняющие соответственно добавление нового сотрудника в таблицу “Личныеданные”, редактирование данных существующего сотрудника(он определяется по регистрационному номеру), удаление существующей записи. При удалении организовать вывод сообщения, информирующего пользователя об удалении. В случае подтверждения намерений удалить запись – она удаляется, а в противном случае – нет.