Настольная СУБД Access 2002


         

Циклы В VBA имеется богатый выбор...



Циклы

В VBA имеется богатый выбор средств организации циклов, которые можно разделить на две основные группы — циклы с условием Do... Loop и циклы с перечислением For...Next.

Циклы типа Do ... Loop используются в тех случаях, когда заранее неизвестно, сколько раз должно быть повторено выполнение блока операторов, составляющего тело цикла. Такой цикл продолжает свою работу до тех пор, пока не будет выполнено определенное условие. Существуют четыре вида циклов Do...Loop, которые различаются типом проверяемого условия и временем выполнения этой проверки. В табл. 13.2 приводится синтаксис этих четырех конструкций.



До обновления





До обновления

Событие До обновления (BeforeUpdate), так же как и следующее событие После обновления (AfterUpdate), возникает при любом изменении данных в записи или элементе управления. Это событие может относиться как к элементу управления, так и к записи в целом. Процедура обработки данного события имеет один параметр — Cancel, использующийся для того, чтобы отменить введенные изменения. Для этого ему необходимо присвоить значение True. Данное событие обычно применяется с целью проверки условий на значение в поле таблицы или записи в целом, если эти условия сложные (простые условия обычно задаются в свойстве Условие на значение (ValidationRule) элемента управления). Условия проверяются сразу для нескольких значений, причем в них используются ссылки на элементы управления в других формах. При разных значениях введенных данных выдаются разные сообщения об ошибках.

При невыполнении условий можно отменить введенные изменения перед переходом на другую запись.

В следующем разделе будет описан порядок возникновения событий, относящихся как к элементу управления, так и к записи в целом.



До подтверждения Del



До подтверждения Del

Удаление записи из базы данных имеет такое большое значение, что с ним связано несколько событий. После события Удаление (Delete) Access выдает специальное окно, запрашивающее подтверждение удаления записи. Событие До подтверждения Del (BeforeDelConfirm) возникает до появления этого окна. Процедура обработки данного события имеет два параметра: Cancel и Response. Присваивая в процедуре значение True параметру Cancel, можно отменить удаление, и окно подтверждения выдаваться на экран не будет. Так что это еще одна возможность отменить удаление программно (третья возможность отмены будет предоставлена пользователю в диалоговом окне подтверждения удаления). Если же параметру Cancel присвоить значение False, то параметр Response можно использовать, чтобы определить, нужно ли выдавать окно подтверждения. Если Response = 1, то запись будет удалена без подтверждения, если же Response установить равным 0, то Access выдаст окно, запрашивающее у пользователя подтверждение удаления записи.

Замечание

Если окно подтверждения удаления не выдается или событие До подтверждения Del (BeforeDelConfirm) не возникает, проверьте установку флажка Изменения записей (Record Changes) в окне Параметры (Options) (на вкладке Правка и поиск, группа Подтверждение).



До вставки



До вставки

Со вставкой новой записи связаны два события: До вставки (Beforelnsert) и описанное далее После вставки (AfterInsert). Событие До вставки (Beforelnsert) происходит, как только пользователь вводит первый символ в новую запись (одно из полей, необязательно первое), но до того, как запись фактически будет создана. Процедура обработки этого события может быть использована для проверки того, разрешена ли вставка. Процедура имеет один параметр: Cancel. Если установить его значение равным True, то вставка записи будет запрещена. После этого события отменить вставку будет уже нельзя, можно только удалить вставленную запись.



Двойное нажатие кнопки



Двойное нажатие кнопки

Событие Двойное нажатие кнопки (DblClick) происходит после быстрого двойного щелчка любой клавиши на форме или элементе управления, при этом интервал между щелчками не должен превышать предельного времени, заданного в панели управления Windows. Событие Двойное нажатие кнопки (DblClick) для формы и элемента управления формы определено так же, как и событие Нажатие кнопки (Click). Однако для элементов управления результат этого события зависит от типа элемента управления. По умолчанию двойной щелчок мыши в текстовом поле приводит к выделению слова, а в объекте OLE — запускает этот объект для редактирования. Вводя процедуру обработки для настоящего события, можно переопределить стандартные действия Access. Процедура имеет один параметр: Cancel. Если присвоить ему в процедуре значение True, то можно отменить это событие.

Замечание

Двойное нажатие кнопки мыши на элементе управления на самом деле вызывает сразу два события: сначала Нажатие кнопки (Click), а потом — Двойное нажатие кнопки (DblClick).



Фильтрация



Фильтрация

Событие Фильтрация (Filter) возникает перед открытием окна фильтра или расширенного фильтра, когда пользователь пытается выполнить команду Изменить фильтр (Filter by Form). Использовать это событие очень удобно, если требуется, например, ввести в фильтр некоторые условия по умолчанию или запретить включать в условия отбора некоторые поля. Чтобы запретить включать некое поле в условие отбора в окне фильтра, достаточно скрыть его в процедуре обработки события Фильтрация (Filter). Правда, это относится только к окну обычного фильтра, т. к. в окне расширенного фильтра выводятся все поля, в том числе и скрытые. Можно даже заменить стандартное окно фильтра своим собственным, в котором пользователь и будет задавать условия отбора. Процедура обработки события имеет два параметра — Cancel и FilterType. Cancel позволяет отменить открытие стандартного окна фильтра, если вместо него будет выводиться специальная форма, для чего нужно присвоить ему значение True. Параметр FilterType определяет, какое окно открывается, и может принимать значения 0 или 1. Значение 0 соответствует обычному фильтру, 1 — расширенному фильтру.



Форматирование



Форматирование

Событие Форматирование (Format) происходит после того, как отобраны данные для отчета, но перед тем, как фактически форматируется каждый раздел отчета. При этом для раздела данных это событие происходит для каждой записи в отчете, что позволяет при необходимости по-разному форматировать каждую запись. Для заголовка группы в отчете событие возникает для каждой группы. Процедура обработки данного события имеет два параметра — Cancel и FormatCount. Cancel позволяет отменить форматирование данного раздела, для чего нужно присвоить ему значение True. Это дает вам возможность пропускать разделы отчета, не оставляя пустого места на странице. FormatCount — счетчик, который считает, сколько раз произошло событие Форматирование (Format).



Язык Visual Basic для приложений



Глава 13. Программирование в Access 2002 Язык Visual Basic для приложений (VBA) Процедуры и функции, их вызов и передача параметров Переменные, константы и типы данных Ссылки на объекты Массивы Область действия переменных и процедур Управляющие конструкции Ветвления Циклы Выход из циклов и процедур Объектные модели Microsoft Access 2002 Основные понятия Объектные модели Microsoft Office 2002 Объектная модель Microsoft Access 2002 Объектные модели доступа к данным Объектная модель Microsoft DAO 3.6 Модель объектов ActiveX для управления данными Объектная модель Visual Basic для приложений Объектная модель Microsoft Office 2002 Использование объектов и семейств Ссылки на объекты Работа с объектами в семействах Свойства и методы объектов Модули как объекты Access Стандартные модули Модули класса Создание модулей Ссылки на объект Module Среда программирования Access 2002 Окно редактора кода Использование окна просмотра объектов Установка ссылок на объектные библиотеки Инструментальные средства отладки Меню Debug Окно Locals Окно Watches Окно Quick Watch Окно Immediate Окно Call Stack Использование комбинаций клавиш быстрого вызова Программирование в формах и отчетах События Access События данных События фокуса События клавиатуры События мыши События печати События фильтра События окна Событие ошибок Событие таймера Последовательности событий Access Последовательность событий фокуса для элементов управления в формах Создание процедур обработки событий Синхронизация данных в связанных формах Проверка дублирования значений первичного ключа Создание перекрестного отчета с изменяющимся числом столбцов Использование функций для обработки событий Выводы





Инструментальные средства отладки



Инструментальные средства отладки

Помимо интеллектуального редактора текста профессиональная среда программирования обычно содержит инструментальные средства отладки. Инструментальные средства отладки призваны дать разработчику максимально ясное представление о том, как работает его программа. И уже искусство разработчика состоит в том, чтобы, используя все имеющиеся в его распоряжении средства, быстро выявить ошибки. Набор средств отладки в Access широк: это и специальное меню Debug (Отладка), и во многом дублирующие его кнопки на панели инструментов, и специальные окна отладки. Далее кратко дается описание каждого средства.



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



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

Обычно для обработки событий в формах и отчетах используют процедуры типа Sub (подпрограммы) или макросы. Однако иногда можно и даже нужно использовать функции. Дело в том, что если в рамках одной формы делается множество однотипных задач, то лучше создать одну процедуру — функцию для выполнения этих задач, описать ее на уровне модуля формы, т. е. в разделе General, а потом вызывать из любого места в форме. Если это необходимо, для такой функции определяется один или несколько параметров, которые передаются при вызове данной функции. И хотя значение, возвращаемое функцией, не используется (а обычно и не определяется), применение ее оправдано не только потому, что требуется писать меньше строк кода, а главным образом потому, что минимизация кода в модуле формы ускоряет ее открытие.

Если же идентичные задачи решаются в разных формах, например, одна и та же реакция предусматривается для одинаковых кнопок в разных формах, то такую функцию нужно написать в стандартном модуле базы данных.

Совет

Если форма сложная, например содержит большое количество элементов управления, в том числе поля со списками, то в целях повышения ее быстродействия рекомендуется удалить модуль формы, а все процедуры обработки событий заменить функциями, которые следует при этом вынести в стандартный модуль.

Допустим, вы отображаете в форме список каких-либо объектов, например счетов клиента. Обычно это делается в подчиненной форме табличного или ленточного вида, в которой отображаются наиболее важные характеристики счета: номер счета, дата выписки, наименование клиента, сумма. И вы хотите дать возможность пользователю при желании посмотреть тот счет, который он выбрал, установив курсор на соответствующую строчку. Это можно сделать, создав процедуру открытия формы счета с нужной записью при двойном щелчке мыши на строчке счета. Естественно, что форма должна открываться при щелчке в любом поле подчиненной формы. Вместо того чтобы в каждом поле подчиненной формы на событие Двойное нажатие (DblClick) создавать процедуру обработки событий, можно создать одну функцию и присоединить ее ко всем полям. Функция будет выглядеть так:

Private Function Order_DblClick()

Dim strCriteria As String

On Error Goto Err Order DblClick

strCriteria = "КодЗаказа = Forms![Заказы клиента]!_ [Заказы клиента подчиненная].form!КодЗаказа"

DoCmd.OpenForm "Заказы", acNormal, , strCriteria

Exit_Order_DblClick: Exit Function

Err_Order_DblClick: ; MsgBox Err.Description Resume Exit_Order_DblClick

End Function

А присоединить эту функцию к событию элемента управления формы можно так, как показано на рис. 13.36. Мы сделали это для формы "Заказы клиента" (Customer Orders) приложения (NorthWind).



Использование комбинаций клавиш быстрого вызова



Использование комбинаций клавиш быстрого вызова

Поскольку работа в редакторе — это главным образом работа с клавиатурой, существует большое количество специальных клавиш и комбинаций клавиш быстрого вызова для выполнения определенных функций. Вы можете увидеть их в меню Run, Debug и View. Список наиболее часто используемых клавиш и их комбинаций приведен в табл. 13.12.



Использование объектов и семейств



Использование объектов и семейств

Несмотря на разнообразие библиотек объектов, методы работы с объектами в процедурах VBA общие и не зависят от того, к какой библиотеке относится конкретный объект. В данном разделе мы как раз и рассмотрим эти общие методы.



Использование окна просмотра объектов



Использование окна просмотра объектов

Окно Object Browser (Обозреватель объектов) позволяет просматривать все объекты, их свойства и методы, доступные для текущего проекта. Объекты могут быть встроенными объектами Access или VBA, объектами, которые вы создали в своем приложении, а также объектами, входящими во внешние библиотеки, на которые имеются ссылки в текущем проекте. Вызвать окно просмотра объектов можно тремя способами:

нажать клавишу <F2> — самый быстрый;
нажать кнопку Object Browser (Обозреватель объектов) на панели инструментов — удобный;
выбрать команду View, Object Browser (Вид, Обозреватель объектов) — если вы забыли другие способы.

Окно Object Browser (Обозреватель объектов) состоит из нескольких списков (рис. 13.21), которые обеспечивают трехуровневое представление информации.

Список Project/Library (Проект/Библиотека) в левом верхнем углу окна содержит перечень всех библиотек и проектов, на которые имеются ссылки в данном проекте. Как минимум, он включает библиотеку Access, библиотеку VBA, библиотеку текущего проекта.

При выборе из списка одной из библиотек в нижнем левом поле Classes (Классы) отображается список следующего уровня — перечень всех объектов, входящих в эту библиотеку. Например, если выбрать библиотеку Access, то в списке Classes вы увидите много знакомых объектов. Выбрав один из них, например DoCmd, в правом поле Members of можно увидеть все методы этого объекта. Если бы мы выбрали объект Form, то в списке справа отобразились бы все свойства и методы объекта Form.



Изменение размера



Изменение размера

Событие Изменение размера (Resize) возникает при открытии формы и при изменении ее размеров. Его обычно применяют, если требуется подстроить размер элементов управления под изменяющиеся размеры формы или вычислить заново вычисляемые элементы. Если нужно, чтобы при каждом изменении размеров формы происходило обновление экрана, используйте в процедуре обработки этого события метод Repaint.

Замечание

При создании процедур обработки событий часто возникают сомнения, какое из двух событий — Открытие (Open) или Загрузка (Load) — использовать (или, соответственно, Закрытие (Close) или Выгрузка (Unload)). Рекомендуется принимать во внимание следующее соображение. Если требуется возможность отменить событие, то пользуйтесь событиями Открытие (Open) и Выгрузка (Unload), в противном случае можно использовать любое.



Клавиша вниз и Клавиша вверх



Клавиша вниз и Клавиша вверх

События Клавиша вниз (KeyDown) и Клавиша вверх (KeyUp) возникают всякий раз, когда пользователь нажимает или отпускает клавишу на клавиатуре и при этом фокус находится на элементе управления или форме. Процедуры обработки этих событий используют, когда требуется определить, какую клавишу нажал пользователь — функциональную, клавишу управления курсором, клавишу цифровой панели или комбинацию клавиш с <Shift>, <Ctrl> или <Alt>. Они имеют два параметра: KeyCode и Shift. Параметр KeyCode — это целое число, представляющее код нажатой клавиши. Параметр Shift позволяет определить, какие сочетания клавиш нажимались: 1 — соответствует <Shift>, 2 — <Ctrl>, 4 — <Alt>, 0 — не использовалось сочетание клавиш. Если же нажималась комбинация клавиш <Shift>, <Ctrl>, <Alt> в любом сочетании, то параметр Shift будет равен сумме значений каждой клавиши.



Кнопка вниз и Кнопка вверх



Кнопка вниз и Кнопка вверх

События Кнопка вниз (MouseDown) и Кнопка вверх (MonseUp) возникают, когда пользователь нажимает и, соответственно, отпускает кнопку мыши, и, в отличие от событий Нажатие кнопки (Click) и Двойное нажатие кнопки (DblClick), оно позволяет определить, какая кнопка нажата. Процедуры обработки этих событий имеют четыре параметра: Button, Shift, х и Y. Эти параметры аналогичны параметрам процедуры для события Перемещение указателя (MouseMove) за исключением первого параметра — Button. Так как в данном случае нажимается конкретная кнопка мыши, параметр Button определяет, какая это кнопка. Если пользователь нажмет сразу две кнопки, то возникнут отдельно события для первой и для второй кнопок.

Замечание

Если кнопка мыши была нажата, когда указатель находился на одном из элементов управления формы, то именно к этому объекту будут относиться все остальные события мыши до последнего Кнопка вверх (MouseUp) включительно.



Колесико мыши



Колесико мыши

Событие возникает, когда пользователь перемещает указатель мыши с помощью колесика скроллирования. Процедура обработки события имеет два параметра:

Page — принимает значение True при перемещении указателя на другую страницу;
Count — количество линий, на которое переместился указатель при прокрутке формы с помощью колесика мыши.



в ближайшее свободное поле заголовок



Листинг 13.1. Процедура обработки события Форматирование верхнего колонтитула

Private Sub PageHeader()_Format(Cancel As Integer,_

FormatCount As Integer)

Dim intx As Integer

' Помещает заголовки столбцов в поля в верхнем колонтитуле.
Me("Head" + Format(0)) = rstReport(0).Name
For intX = 1 To intColumnCount - 1

Me("Head" + Format(intX)) =_

MonthRus(CInt(rstReport(intX).Name))

Next intX

' Вводит в ближайшее свободное поле заголовок "Итого".
Me("Head" + Format(intColumnCount)) = "Итого"

' Скрывает пустые поля в верхнем колонтитуле.

For intX = (intColumnCount +1) То conTotalColumns - 1

Me("Head" + Format(intX)).Visible = False
Next intX
End Sub

В этой процедуре используется функция MonthRus, которая по порядковому номеру месяца выдает его название. Мы здесь не приводим текста этой функции, надеясь, что вы сможете написать ее сами conTotalColumns — константа, которая описана на уровне модуля и значение которой определяет максимальное число столбцов в отчете. В данном примере conTotalColumns равна 14.

что не достигнут конец набора



Листинг 13.2. Процедура обработки события Форматирование области данных 1

Private Sub Detaill_Format(Cancel As Integer,_ FormatCount As Integer)

' Вводит значения в поля и скрывает пустые поля.
Dim intX As Integer

' Проверяет, что не достигнут конец набора записей.
If Not rstReport.EOF Then

'Помещает значения из набора записей в поля области данных
If Me.FormatCount = 1 Then

For intX = 0 To intColumnCount - 1

' Преобразует пустые значения в 0.

Me ("Col" + Format(intX)} =_

xtabCnulls(rstReport(intX))

Next intX

' Скрывает неиспользуемые поля в области данных.

For intX = intColumnCount + 1 То conTotalColumns - 1

Me("Col" + Format(intX)).Visible = False Next intX

' Переходит к следующей записи в наборе. rstReport.Move
Next
End If
End If
End Sub

Свойство FormatCount отчета содержит значение, равное количеству столбцов для форматирования, поэтому в процедуре проверяется это свойство, и присвоение значений полям в области данных выполняется, только если это значение не 0. В процедуре используется также функция xtabCnulls, преобразующая пустое значение в 0.

Для события Печать (On Print) области данных отчета нужно создать процедуру, которая бы суммировала значения по строке отчета, выводила полученное значение в последнем столбце и, кроме того, добавляла эту сумму в массив итоговых значений по столбцам (листинг 13.3). Массив итоговых значений по столбцам IngRgColumnTotal и переменная IngReportTotal, определяющая общий итог, должны быть описаны на уровне модуля. Кроме того, они должны быть инициализированы, т. е. им нужно присвоить начальные значения 0. Это можно сделать в процедуре обработки события Загрузка (On Load) отчета.

Cancel As Integer, PrintCount As



Листинг 13.3. Процедура обработки события Печать области данных

Private Sub Detaill_Print( Cancel As Integer, PrintCount As Integer)
Dim intX As Integer
Dim IngRowTotal As Long

' Вычисляет сумму по строке и добавляет ее к итоговому значению. ' по столбцу и общему итогу

If Me.PrintCount = 1 Then IngRowTotal = 0
For intX = 1 To intColumnCount - 1

' Начиная со столбца 1 (первый столбец с перекрестными
' значениями), вычисляет сумму по строке.
lngRowTotal = IngRowTotal + Me("Col" + Format(intX))
' Добавляет итоговое значение для текущего столбца.

IngRgColurenTotal(intX) = IngRgColumnTotal(intX) +_

Me ("Col" + Format(intX))

Next intX

' Заносит сумму по строке в поле в области данных. Me("Col" + Format(intColumnCount)) = IngRowTotal
' Прибавляет сумму по строке к общему итогу.
IngReportTotal = IngReportTotal + IngRowTotal
End If
End Sub

Процедура обработки события Печать (On Print) примечания отчета должна заполнить поля примечания итоговыми значениями по столбцам из массива IngRgColumnTotal (листинг 13.4).

Процедура обработки события Печать примечания



Листинг 13.4. Процедура обработки события Печать примечания

Private Sub ReportFooter4_Print(Cancel As Integer,_

PrintCount As Integer)

Dim intX As Integer

' Помещает суммы по столбцам в поля примечания.

For intX = 1 То intColumnCount - 1

Me("Tot" + Format(intX)) = IngRgColumnTotal(intX)

Next intX

' Помещает общий итог в поле примечания.

Me("Tot" + Format(intColumnCount)) = IngReportTotal

' Скрывает неиспользуемые поля в примечании отчета.

For intX = intColumnCount + 1 То conTotalColumns - 1

Me("Tot" + Format(intX)).Visible = False

Next intX

End Sub

Для корректной работы нужно еще добавить две небольшие процедуры в свойства отчета:

при закрытии отчета нужно закрыть базовый набор записей — обработка события Закрытие (On Close);

при отсутствии данных в базовом наборе записей нужно закрыть этот набор и прервать формирование отчета — событие Отсутствие данных (On No Data).

Ниже приведены обе эти процедуры (листинги 13.5 и 13.6).



Процедура обработки события Закрытие отчета



Листинг 13.5. Процедура обработки события Закрытие отчета

Private Sub Report_Close()

On Error Resume Next

rstReport.Close

End Sub



He найдены записи, удовлетворяющие указанным_



Листинг 13.6. Процедура обработки события Отсутствие данных отчета

Private Sub Report_NoData(Cancel As Integer)

MsgBox " He найдены записи, удовлетворяющие указанным_

условиям.", vbExclamation, "Записи не найдены"

rstReport.Close Cancel = True
End Sub

Массивы



Массивы

Массив — это переменная, в которой хранится одновременно несколько значений одинакового типа. Формальное определение массива таково: он представляет собой совокупность однотипных индексированных переменных.

Количество используемых индексов массива также может быть различным. Чаще всего применяются массивы с одним или двумя индексами, реже — с тремя, еще большее количество индексов встречается крайне редко. В VBA допускается использовать до 60 индексов. О количестве индексов массива обычно говорят как о размерности массива. Массивы с одним индексом называют одномерным, с двумя — двумерными и т. д. Массивы с большим количеством измерений могут занимать очень большие объемы памяти, так что следует быть осторожным в их применении.

Прежде чем использовать массив, нужно обязательно объявить его с помощью оператора Dim и указать при этом тип хранящихся в массиве значений. Все значения в массиве обязаны принадлежать к одному типу данных. Это ограничение на практике можно обойти, использовав при объявлении массива тип Variant — в этом случае элементы массива смогут принимать значения разных типов. Вот синтаксис оператора объявления массива:

Dim <имяМассива> (<размер1>, <размер2>, ...) As <типДанных>

где указанные в скобках величины <размер1>, <размер2> и т.д. задают размеры массива — количество индексов и максимально допустимое значение для каждого. конкретного индекса. При этом индексирование элементов массива по умолчанию начинается с нуля. Так, объявление

Dim Array1 (9) As Integer

определяет одномерный массив из 10 элементов, являющихся переменными целого типа, а объявление

Dim Array2 (4, 9) As Variant

определяет двумерный массив из пятидесяти (5x10) элементов, являющихся переменными универсального типа variant.

Замечание

В качестве стандартного значения нижней границы для допустимых значений индекса может использоваться не только ноль. Можно изменить это стандартное значение с помощью оператора Option Base. Например, если поместить в начало вашего модуля оператор Option Base 1, то индексирование элементов массивов по умолчанию будет начинаться не с нуля, а с единицы.

При объявлении массива можно указать не только верхнюю границу индекса, но и его нижнюю границу, т. е. явно задать диапазон изменения конкретного индекса массива, причем нижняя граница может быть любым целым числом, необязательно неотрицательным. Вот синтаксис такого определения:

Dim <имяМассива> (<мин1> То <макс1>, ...)

As <типДанных>

Например, если вы собираетесь работать с массивом метеорологических данных, представляющих собой средние дневные температуры за последние две недели, то может оказаться весьма удобным дать следующее определение массива:

Dim Temperature (-14 То 0)

As Single

При этом, например, Temperature (-2) будет соответствовать позавчерашней температуре, а для определения нужного индекса для интересующего вас дня будет достаточно использовать разность дат.

В приведенных выше примерах речь шла о массивах фиксированного размера, количество элементов в которых явно указано во время описания массива в операторе Dim. Такие массивы называются статическими. В VBA допускается использование и динамических массивов, размеры которых при описании не фиксируются. Определение размера динамического массива может быть сделано непосредственно во время выполнения программы.

При определении динамического массива в операторе Dim после имени массива стоят лишь пустые скобки и описание типа переменных. Количество индексов и диапазон их изменения не задаются. Однако перед тем, как использовать массив, нужно выполнить оператор ReDim, который задаст размерность и диапазоны изменения индексов динамического массива.

Синтаксис объявления и определения размеров динамического массива таков:

Dim <имяМассива> ( ) As <типДанных>

ReDim <имяМассива> (<размер1>, <размер2>, . . . )

Вот как может выглядеть объявление, определение размеров и использование динамического массива, а затем последующее изменение размерности и размеров этого же массива:

Dim dArray ( ) As Variant

ReDim dArray ( 1 , 2 )

dArray (0, 0) = 2

dArray (0, 1) = 3

k = dArray (0, 0) + dArray (0, 1)

ReDim dArray (k)

dArray (0) = "Строка1"

В этом примере массив dArray сначала определяется как двумерный массив из шести элементов, а затем переопределяется как одномерный массив, причем верхняя граница индекса задается значением переменной k.

Замечание

Чтобы определить текущую нижнюю или верхнюю границу массива, можно использовать функции LBound и Ubound соответственно.

Учтите, что по умолчанию при изменении размеров массива ему заново выделяется память и текущие значения его элементов теряются. Чтобы не потерять текущие значения массива при изменении его размеров, используется ключевое слово Preserve. Например, чтобы увеличить размер массива dArray на один элемент, не потеряв значений существующих элементов, можно поступить следующим образом:

ReDim Preserve dArray (UBound( dArray) + 1)



Меню Debug



Меню Debug

Меню Debug (Отладка) и специальная панель инструментов Debug (Отладка) представлены на рис. 13.25. Назначение команд меню описано в табл. 13.11.



Модель объектов ActiveX для управления данными



Модель объектов ActiveX для управления данными

Объекты управления данными ActiveX (ADO/ ActiveX Data Objects) предназначены для обеспечения доступа к источникам данных разных видов, от текстовых файлов до распределенных баз данных. ADO представляет собой объектно-ориентированный интерфейс для приложений, использующих OLE DB. OLE DB — это программный интерфейс, удовлетворяющий спецификации COM (Component Object Model, компонентная модель объектов), который предоставляет унифицированный способ доступа к различным источникам данных. Интерфейс OLE DB разрабатывался с целью получения оптимальной функциональности для приложений разных видов и поэтому не является простым в использовании. ADO — промежуточное звено между приложением и OLE DB, предоставляющее разработчикам приложений удобный объектно-ориентированный интерфейс.

Существует три объектных модели, которые вместе обеспечивают те функции работы с данными, которые реализуются объектами DАО:

Microsoft ActiveX Data Objects 2.6 (ADODB);
Microsoft ActiveX Data Objects Extensions for DDL and Security 2.6 (ADOX);
Microsoft Jet and Replication Objects 2.6 (JRO).

Стандартный набор функций для работы с данными распределяется между этими тремя моделями следующим образом:

Управление данными. Объектная модель ADODB обеспечивает вашему приложению доступ к источнику данных и возможность отбирать для просмотра и изменять эти данные. Однако она не предоставляет возможности изменять структуру таблиц и других объектов источника данных.
Определение данных и защита. Объектная модель ADOX позволяет программно изменять структуру объектов в источнике данных, в частности добавлять и удалять таблицы, изменять структуру таблиц, создавать и изменять запросы, представления и хранимые процедуры, а также управлять схемой защиты данных: создавать группы пользователей и отдельных пользователей, наделять их требуемыми правами доступа к объектам.
Репликация и службы ядра базы данных Jet. Объектная модель JRO позволяет создавать, модифицировать и синхронизировать реплики. Она была спроектирована специально для доступа к объектам Jet и, в отличие от моделей ADODB и ADOX, может работать только с базами данных Access.

Краткое описание объектов моделей ADO приведено в табл. 13.5—13.7.



Модули как объекты Access


Код VBA в приложении Access содержится в модулях. Модули являются объектами Access, такими же, как таблицы, запросы, формы, отчеты, страницы и макросы, о чем свидетельствует ярлык на панели объектов в окне База данных (Database). Основное содержание модулей — это процедуры на языке VBA. Существуют два типа модулей: стандартные модули и модули класса.



Модули класса



Модули класса

Вторым типом модуля в Access является модуль класса. Модуль класса отличается от стандартного модуля тем, что, кроме процедур, он содержит описание объекта и используется для создания объектов. Процедуры, определенные в этом модуле, являются методами и свойствами объекта. Примерами модулей класса являются модули форм и отчетов.

Модули форм и отчетов связаны с конкретной формой или отчетом и содержат процедуры обработки событий для этой формы или отчета. Модуль формы не создается сразу при создании новой формы. Он создается и связывается с формой, как только вы попытаетесь создать первую процедуру обработки событий для этой формы или одного из элементов управления формы или же нажмете кнопку Программа (Code) в окне Конструктора формы.

Чтобы убедиться в этом, откройте любую форму приложения "Борей" (Northwind) в режиме Конструктора и посмотрите свойства этой формы. На вкладке Другие (Others) есть свойство Наличие модуля (Has Module). Оно должно иметь значение Нет (No). После нажатия кнопки Программа (Code), которая служит для открывания редактора кода VBA, значение этого свойства изменится на Да (Yes) (рис. 13.9).



Нажатие клавиши



Нажатие клавиши

Событие Нажатие клавиши (KeyPress) происходит, если пользователь нажимает и отпускает любую комбинацию клавиш для элемента управления или формы, имеющей фокус. В отличие от событий Клавиша вниз (KeyDown) и Клавиша вверх (KeyUp), данное событие не происходит, когда нажимаются функциональные клавиши, клавиши управления курсором и клавиши <Shift>, <Ctrl> или <Alt>. Кроме того, эти события различны для верхнего и нижнего регистров. Процедура обработки настоящего события имеет один аргумент: KeyAscii — целое число, представляющее код нажатой клавиши.

Если пользователь нажимает и удерживает некоторую клавишу, то возникают повторяющиеся события Клавиша вниз (KeyDown) и Нажатие клавиши (KeyPress) до тех пор, пока он не отпустит клавишу. Тогда возникает событие Клавиша вверх (KeyUp).

Если результатом нажатия клавиши является перевод фокуса с одного элемента на другой, то событие Клавиша вниз (KeyDown) возникает для первого элемента, а события Нажатие клавиши (KeyPress) и Клавиша вверх (KeyUp) — для второго.

Если в результате нажатия клавиши появляется диалоговое окно, то возникают события Клавиша вниз (KeyDown) и Нажатие клавиши, а событие Клавиша вверх (KeyUp) не возникает.



Нажатие кнопки



Нажатие кнопки

Это наиболее широко распространенное событие. Оно возникает как в самой форме, так и в элементах управления формы. Для формы событие Нажатие кнопки (Click) возникает, когда пользователь щелкает мышью на пустой области формы или на области выделения записи в форме. Для элемента управления событие Нажатие кнопки (Click) возникает при щелчке мыши не только на самом элементе, но и на присоединенной к нему надписи. Однако для элемента управления оно возникает не только при щелчке мыши, но и в некоторых других случаях, а именно:

при выборе элемента из списка, независимо от того, был ли он выбран с помощью мыши или клавиш управления курсором с последующим нажатием <Enter>;
при нажатии клавиши <Пробел>, когда фокус установлен на флажке, переключателе или командной кнопке;
при нажатии клавиши <Enter> в форме, которая содержит кнопку свойства По умолчанию (Default) со значением Да, тогда именно на эту кнопку по умолчанию устанавливается фокус;
при нажатии клавиши <Esc> в форме, которая содержит кнопку свойства Отмена (Cancel) со значением Да;
при нажатии клавиш доступа, если они связаны с кнопками на форме.

Таким образом, процедуры обработки события Нажатие кнопки (Click) для кнопок запускаются независимо от того, каким образом эта кнопка выбрана — щелчком мыши, нажатием клавиши <Enter> или клавиши доступа. Процедура обработки события запускается только один раз. Если требуется, чтобы она запускалась несколько раз, пока кнопка остается нажатой, необходимо использовать свойство Автоматический повтор (AtitoRepeat) для кнопки. Если нужно определить, какой кнопкой мыши выполнялся щелчок, следует использовать события Кнопка вниз (MouseDown) и Кнопка вверх (MouseUp).



Объектная модель Microsoft Access 2002



Объектная модель Microsoft Access 2002

Объектная модель Microsoft Access 2002 реализована в виде набора объектов, собранных в библиотеке Access. Основным элементом в иерархии объектов библиотеки Access является объект Application. Он содержит ссылки на все объекты и семейства объектов Microsoft Access. Каждый объект из библиотеки Access имеет в качестве свойства объект Application (в том числе и сам объект Application имеет свойство Application), который ссылается на активное приложение Microsoft Access.

Иерархия объектов и семейств объектов Microsoft Access 2002 представлена на рис. 13.1 — 13.3. Названия объектов, являющихся элементами семейств, приведены в скобках. Новые объекты, появившиеся в Microsoft Access 2002, отмечены звездочкой. Иерархия объектов, представленная на рисунках, образована следующим образом:

каждый объект может содержать набор свойств, часть из которых может являться ссылками на другие объекты;
в каждый новый уровень иерархии входят объекты, ссылки на которые хранятся в объектах, расположенных на предыдущем уровне иерархии.
Если свойство объекта представляет собой ссылку на объект, определенный в другой библиотеке (не в библиотеке Access), для него приводится название этой библиотеки.




Data Access Objects) создавались, как



Объектная модель Microsoft DAO 3.6

Объекты доступа к данным (DAO, Data Access Objects) создавались, как объектно-ориентированный интерфейс для ядра баз данных Jet фирмы Microsoft. В ранних версиях Microsoft Office доступ к данным обеспечивался исключительно ядром Jet. Сначала ядро Jet могли использовать только Access и Visual Basic, но с выходом пакета Microsoft Office 95 ядро Jet стало сервером Automation, что позволило использовать DАО для доступа к данным из любого клиента Automation. В версии Office 97 компоненты Excel, Word и PowerPoint стали клиентами Automation и вышла новая версия DAO 3.5. В DАО 3.5 появился новый режим доступа к данным ODBCDirect, который позволяет манипулировать данными в обход ядра Jet, напрямую связываясь с источниками данных ODBC no технологии "клиент-сервер". За счет прямого доступа к данным получается выигрыш в производительности, при этом конечный пользователь имеет стандартный объектно-ориентированный интерфейс доступа к различным типам данных, начиная от баз данных Access до баз данных ISAM (Indexed Sequential Access Method — индексно-последовательный метод доступа) и SQL. Отсюда можно заключить, что DАО — это унифицированный набор объектов для доступа к данным.

В Microsoft Office 2000 вошли новая версия DAO 3.6 и новая версия Microsoft Jet 4.0, в которой реализована поддержка Unicode, т. е. в базах данных появилась возможность хранить символы любых национальных алфавитов одновременно. В версии Microsoft Access 2002 используются те же версии Jet и DАО.

DАО версии 3.5 и выше включает две объектные модели, соответствующие двум типам "рабочей области" (сеанс работы с базой данных), в зависимости от того, используется ли ODBCDirect. При доступе к данным с помощью ядра Microsoft Jet применяется рабочая область Microsoft Jet. В случае прямого доступа к источнику данных ODBC используется рабочая область ODBCDirect. Тип рабочей области и связанного с ней источника данных определяет, какие объекты, свойства и методы DАО можно использовать (рис. 13.4, 13.5).

Применяйте рабочую область Microsoft Jet для доступа к базам данных Jet (таким, как MDB-файлы Access) или другим настольным базам данных ISAM или в том случае, когда требуется использовать уникальные средства ядра Jet, такие как объединение данных в разных форматах.

Применяйте в клиентском приложении рабочую область ODBCDirect вместо рабочей области Jet в следующих случаях:

если нужно только выполнить запрос или хранимую процедуру на сервере баз данных, таком как SQL Server;
когда требуется воспользоваться специфическими возможностями ODBCDirect, такими как пакетное обновление записей, обновленные записи оптируются на локальном компьютере;
когда требуется асинхронное выполнение запроса, запрос выполняется в фоновом режиме, не останавливая выполнение других




Объектная модель Microsoft Office 2002



Объектная модель Microsoft Office 2002

Иерархия объектов Microsoft Office 2002 представлена на рис. 13.7.




Объектная модель Visual Basic для приложений



Объектная модель Visual Basic для приложений

Объект

Тип

Описание

Collection

Объект из библиотеки VBA

Упорядоченная совокупность объектов, с которой можно обращаться как с единым объектом

Debug

Объект

Позволяет выводить текущую информацию в окно отладки непосредственно во время выполнения кода на VBA

Dictionary

Объект из библиотеки Scripting

Объект, представляющий пару: ключ и элемент. Представляет собой аналог элемента ассоциативной памяти

Drives

Семейство из библиотеки Scripting

Содержит объекты Drive, предоставляющие информацию (только для чтения) обо всех доступных дисках. Является свойством объекта FileSystemObject

Drive

Объект из библиотеки Scripting

Предоставляет доступ к свойствам конкретного локального или сетевого диска

Err

Объект из библиотеки VBA

Предназначен для обработки ошибок Automation и ошибок модулей VBA во время выполнения кода наЛ/ВА

Files

Семейство из библиотеки Scripting

Содержит объекты File и представляет собой совокупность всех файлов в данной папке. Является свойством объекта

FileSystemObject

File

Объект из библиотеки Scripting

Предоставляет доступ ко всем свойствам файла на диске

FileSystemObject

Объект из библиотеки Scripting

Предоставляет доступ к файловой системе компьютера

Folders

Семейство из библиотеки Scripting

Содержит объекты Folder и представляет собой совокупность всех папок внутри данной папки. Является свойством объекта Folder (свойство называется

SubFolders)

Folder

Объект из библиотеки Scripting

Предоставляет доступ ко всем свойствам папки на диске

TextStream

Объект из библиотеки Scripting

Обеспечивает последовательный доступ к текстовому файлу

UserForm

Абстрактный объект VBA

Object

Представляет объект — окно или диалоговое окно, являющееся частью пользовательского интерфейса приложения. Характеристики этого объекта определяются пользователем

UserForms

Семейство из библиотеки VBA

Содержит объекты object, соответствующие объектам User Form, и представляет собой совокупность пользовательских форм, загруженных в данный момент в приложение. Это семейство является свойством объекта Global из библиотеки VBA



Объектные модели доступа к данным



Объектные модели доступа к данным

Объекты доступа к данным предназначены для программного доступа и управления данными в локальной или удаленной базе данных, а также для программного управления самими базами данных, их объектами и структурой. В Microsoft Access 2002, так же как и в Microsoft Access 2000, сохранилась возможность двух способов работы с данными:

старый, посредством DAO (Data Access Objects); новый, посредством ADO (ActiveX Data Objects). Каждому из этих способов соответствует своя объектная модель.



Язык Visual Basic for Applications



Язык Visual Basic for Applications является объектно-ориентированным языком программирования. Стандартные объекты Visual Basic представляют собой основное средство манипуляции с данными Microsoft Access и других приложений семейства Microsoft Office. Знание технологии объектно-ориентированного программирования и состава объектных моделей Visual Basic позволяет разрабатывать профессиональные приложения, выполняющие всю необходимую обработку данных.



Объектные модели Microsoft Office 2002



Объектные модели Microsoft Office 2002

Управление приложениями семейства Microsoft Office 2002 осуществляется интерактивно — с помощью интерфейса пользователя или программно — с помощью объектных моделей. Каждый из компонентов Microsoft Office предоставляет свои объектные модели в виде одноименной библиотеки объектов (файл с расширением olb), которая может быть использована в других приложениях. Microsoft Access 2002, как компонент Microsoft Office, имеет такую библиотеку — Microsoft Access 10.0 Object Library. Доступ и управление данными в Microsoft Access могут осуществляться с помощью объектных моделей, реализованных в нескольких библиотеках:

библиотека объектов Microsoft Access (Microsoft Access 10.0 Object Library);
библиотека объектов доступа к данным (Microsoft DAO 3.6 Object Library);
библиотека объектов ActiveX (Microsoft ActiveX Data Objects 2.6);
расширения ADO для поддержки DDL и защиты информации (Microsoft ADO Extensions 2.6 for DDL and Security);
библиотека объектов Microsoft Jet и репликации (Microsoft Jet and Replication Objects 2.6).
Кроме этого, в приложениях Access обычно используются:

библиотека объектов Visual Basic (Microsoft Visual Basic for Applications); библиотека объектов Microsoft Office (Microsoft Office 10.0 Object Library). Две эти библиотеки являются общими для всех приложений Microsoft Office.
Кроме перечисленных библиотек объектов, при написании программ в приложениях Access могут использоваться библиотеки, предоставляемые другими приложениями Microsoft Office, например Microsoft Excel 10.0 Object Library или Microsoft Word 10.0 Object Library. В этом случае приложение Access выступает в качестве клиентского приложения Automation, обеспечивая совместную работу нескольких компонентов Microsoft Office. (Об использовании Automation для интеграции приложений Microsoft Office см. гл. 15.)



Область действия переменных и процедур



Область действия переменных и процедур

Все процедуры, функции, переменные и константы в VBA имеют свою область действия. Это означает, что они могут использоваться только в определенном месте программного кода — именно там, где они описаны. Например, если переменная А описана с помощью оператора Dim в теле процедуры с именем Prod, именно эта процедура и является ее областью действия. Таким образом, если имеется другая процедура Ргос2, вы не можете использовать в ней эту же переменную. Если вы попытаетесь сделать это, то либо получите сообщение об ошибке из-за использования неописанной переменной (в том случае, если используется упоминавшийся выше оператор Option Explicit) либо просто получите другую переменную — с тем же самым именем, но никак не связанную с одноименной переменной из первой процедуры.

Начнем с определения области действия переменных. То, в каком месте программы и как именно описана переменная, определяет область ее действия и то, как долго она "живет" в памяти и сохраняет присвоенное ей значение. Имеются три различных уровня при определении области действия переменных:

уровень процедуры;
уровень модуля;
уровень проекта.

Чтобы определить переменную на уровне процедуры, ее описание помещается в тело данной процедуры, и тогда это будет локальная переменная этой процедуры.

Чтобы определить процедуру на уровне модуля и сделать её тем самым доступной для совместного применения во всех процедурах данного модуля, следует поместить ее описание в секции объявлений модуля — перед текстом каких-либо процедур или функций. При этом может использоваться и явное описание области действия: ключевое слово Dim в этом случае заменяется на ключевое слово Private. Нет никакой разницы в том, какой из этих описателей вы используете.

Наконец, чтобы описать переменную на уровне проекта, необходимо расположить ее описание в секции объявлений одного из модулей проекта и при этом обязательно должно использоваться ключевое слово Public. Описанные таким образом переменные могут применяться в любом модуле проекта.

Замечание

Все вышесказанное относится и к описанию и определению области действия констант и массивов.

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

Тем не менее статистическая переменная не может быть использована в других процедурах. Изменяется лишь время ее жизни, но не область действия. Если произойдет повторный вызов той же самой процедуры, в которой была описана статистическая переменная, то эта переменная сохранит свое прежнее значение, которое она имела в момент завершения работы этой процедуры при предыдущем вызове. Обыкновенные, не статистические, переменные всякий раз инициализируются заново и получают при входе в процедуру пустые значения.

Перейдем к обсуждению области действия процедур и функций. Процедуры и функции имеют только два уровня областей действия: уровень модуля и уровень проекта. По умолчанию используется уровень проекта. Таким образом, процедура или функция может быть вызвана любой другой процедурой или функцией в этом проекте. При описании процедур и функций на уровне проекта может также использоваться необязательное ключевое слово Public. Никакого воздействия на процедуру наличие или отсутствие этого слова не оказывает.

Если требуется описать процедуру, используемую только на уровне модуля, то для этого применяется ключевое слово Private. Учтите, что такое описание не только сужает область действия для процедуры, но и запрещает ее использование как самостоятельной процедуры — ее можно вызвать только из другой процедуры.

Наконец, при описании процедур или функций может использоваться и ключевое слово static. Оно никак не влияет на область действия процедуры, но воздействует на все переменные, описанные внутри этой процедуры или функции. В этом случае все локальные переменные получают статус Static и тем самым остаются в памяти после завершения такой процедуры и при повторном ее вызове сохраняют свои прежние значения.

Рассмотрим пример модуля, начинающегося следующим образом:

Public Al As String Private A2 As Integer

Dim A3 As Single

Sub Prod ()

Dim A4 As Integer

Static A5 As Integer

Al = "Текстовая строка 1"

A2= 2

A3 = 3.14

A4 = A4 + 4

A5 = A5 + 5

MsgBox A4

MsgBox A5

End Sub

Sub Proc2 () Procl

MsgBox Al

MsgBox A2

MsgBox A3

MsgBox A4

MsgBox A5

Procl End Sub

В этом примере переменная А1 определена на уровне всего проекта (использовано ключевое слово Public), переменные А2 и A3 определены на уровне модуля, переменная А4 — только на уровне процедуры Prod, а переменная А5 хотя и определена в теле процедуры Procl, но описана как статическая переменная.

При вызове процедуры Рrос2 произойдет следующее: из этой процедуры будет в свою очередь вызвана процедура Procl, которая присвоит значения всем пяти переменным А1, А2, A3, А4 и А5, а затем покажет текущие значения переменных А4 и А5 в диалоговом окне.

После завершения этой процедуры будут выведены текущие значения переменных А1—А5 из процедуры Ргос2. При этом окажется, что переменные А1—A3 сохранили свои значения, поскольку они описаны на уровне модуля, а переменные А4 и А5 принимают пустые значения, поскольку областью действия этих переменных являются процедуры, в которых они используются. Никакие изменения этих переменных внутри одной из процедур не имеют отношения к аналогичным переменным из другой процедуры — на самом деле это разные переменные, просто для них используются совпадающие имена.

Затем происходит еще один вызов процедуры Procl, и она вновь начинает изменять и выводить на экран значения переменных А4 и А5. При этом переменная А4 вновь получит значение 4, поскольку при новом вызове процедуры для этой переменной будет заново выделена память и она будет инициализирована пустым значением. В отличие от А4, переменная А5, описанная как статическая переменная, сохранит свое прежнее значение от предыдущего вызова этой процедуры, в результате ее значение при повторном вызове окажется равным 10.



Окно Call Stack



Окно Call Stack

Окно Call Stack (Стек вызовов) содержит список всех незавершенных процедур приложения и используется для трассировки вложенных процедур. При этом самая перва из вызванных процедур будет размещаться в нижней части стека, а самая последняя — в верхней части. Наименование процедуры состоит из трех частей: имени проекта, имени модуля (в том числе модуля формы), имени процедуры (рис. 13.31).



Окно Immediate



Окно Immediate

Кроме всех перечисленных окон отладки, в Access 2002 сохранилось окно Immediate (Отладка) для тестирования данных и процедур, которое присутствовало еще в Access 2.0. Это окно может быть использовано двояким образом: можно вручную проверить значение выражения с помощью команды Print или "?" (рис. 13.30) или, вставив в код программы команду Debug.Print, посмотреть в этом окне контрольную печать.



Окно Locals



Окно Locals

Специальные окна отладки используются главным образом для того, чтобы просматривать промежуточные значения данных: переменных, выражений, свойств объектов и т. д. К ним относятся два окна: Locals (Локальные) и Watches (Контрольные). Чтобы познакомиться с этими окнами, давайте установим точку останова на одной из команд написанной нами ранее процедуры 3aKaaH_Click в форме "Клиенты" (Customers). Для этого нужно:

Открыть данную процедуру в окне редактора кода, как это описывалось выше.
Установить курсор на строку DoCmd.OpenForm "Заказы", acNormal, stLinkCriteria
Нажать кнопку на панели инструментов с изображением руки или выбрать команду Toggle Breakpoint в меню Debug. Строка будет выделена коричневым фоном и на панели слева, напротив этой строки, появится специальный значок — жирная коричневая точка.

Совет

Самый простой и естественный способ установки точек останова: щелкните мышью по серой полосе у левого края окна редактора напротив нужной строки. Снять точку можно щелчком мыши по коричневой точке напротив нужной строки.

Теперь окно модуля можно закрыть, открыть форму "Клиенты" (Customers) в режиме формы и нажать кнопку Заказы клиента. При нажатии этой кнопки запускается наша процедура обработки событий и, как только выполнение дойдет до помеченной строки, произойдет останов, а на экране появится окно редактора кода, в котором помеченная строка выделена желтым цветом, означающим, что это текущая команда. Нажмите кнопку Local Window или выберите соответствующую команду из контекстного меню редактора. Тогда в нижней части экрана появится новое окно Locals (Локальные) (рис. 13.26). В этом окне можно увидеть все локальные переменные и константы текущей процедуры, а также иерархический список свойств всех объектов формы, который скрывается за коротеньким словом ме. Именно эти свойства и интересуют, как правило, разработчика, т. к. в большинстве случаев значения переменных в точке останова можно увидеть просто подведя курсор к этой переменной в окне редактора. Тогда появляется всплывающая подсказка со значением переменной, как это показано на рис. 13.26.

Замечание

Если подсказка не появляется, проверьте значение флажка Auto Value Tips на вкладке Editor окна Options.

Если вы будете выполнять процедуру по шагам, то сможете наблюдать, как меняются значения свойств.

Рис. 13.26. Установка точки прерывания в программе



Окно Quick Watch



Окно Quick Watch

Окно Quick Watch (Быстрый просмотр) используется для просмотра значения свойства, переменной или выражения, которое не определено заранее как контрольное значение. Чтобы открыть это окно, необходимо:

Выделить в тексте программы интересующее выражение.
Нажать кнопку Quick Watch на панели инструментов, или выбрать команду Debug, Quick Watch (Быстрый просмотр), или нажать комбинацию клавиш <Shift>+<F9>.

Диалоговое окно на рис. 13.29 отображает значение переменной stLinkCriteria.



Окно редактора кода



Окно редактора кода

Для того чтобы открыть окно редактора, достаточно открыть любой модуль Access (рис. 13.12).

Замечание

Даже в локализованных версиях Access окно редактора кода VBA, а также все другие диалоговые окна, составляющие среду программирования VBA, традиционно не локализуются. Поэтому все рисунки в этом разделе главы, а также экранные термины (названий команд меню, диалоговых окон и т. д.) приводятся в нелокализованном варианте.



Окно Watches



Окно Watches

Окно Watches (Контрольные) содержит контрольные выражения. Данные выражения контролируются самой Access в процессе выполнения программы, и когда выполнение программы останавливается, в этом окне можно увидеть текущие значения этих выражений. Можно составить контрольное выражение таким образом, что приложение останавливается, когда это выражение принимает определенное значение. Такой прием, например, используется, когда отлаживаются длинные циклы, которые слишком долго выполнять по шагам.

Для того чтобы отследить контрольные значения, их сначала нужно задать. Для этого используется команда Add Watch (Добавить контрольное значение) в меню Debug (Отладка). Добавлять контрольные значения можно как в обычном режиме редактирования кода, так и в режиме останова. При выборе команды появляется диалоговое окно Add Watch (Добавление контрольного значения) (рис. 13.27). В поле Expression (Выражение) можно ввести контрольное значение — это может быть переменная, свойство или любое допустимое выражение. Давайте введем в это поле условие останова приложения stbinkcritria <> "", а в группе переключателей Watch Type (Тип контрольного значения) выберем переключатель Break When Value Is True (Останов, если значение истинно).



Основные понятия



Основные понятия

Начнем с определения основных понятий, которые потребуются для понимания работы с объектами в языке VBA. Такими понятиями в данном случае будут:

объект семейство метод класс свойство событие
объектная модель

Объект — это абстракция, с которой мы оперируем в объектно-ориентированных г языках программирования. Объект обладает собственными характерными признаками, отличающими его от других объектов, и имеет свое поведение. Примерами объектов Access являются уже известные вам таблицы, формы, отчеты, запросы.

Класс представляет собой описание совокупности однотипных объектов. Класс можно сравнить с типом данных, где переменной такого специфического типа является объект. В этом случае говорят, что объект представляет собой экземпляр определенного класса.

Каждый объект имеет свойства и методы, которые различны у разных классов объектов, но применяются они одинаково, в чем вы скоро убедитесь на примерах использования объектов в процедурах VBA.

Свойством называют отдельную характеристику объекта или класса. Например, знакомые уже вам свойства формы являются свойствами объекта Form. Свойство .объекта может принимать определенное значение. Например, свойство Вывод на экран (Visible) может принимать значение True или False, в зависимости от чего форма будет появляться или исчезать с экрана.

Метод представляет собой процедуру (или функцию) объекта или класса. Совокупность методов объекта определяет его "поведение". Например, объект Form имеет метод Refresh, вызов которого позволяет обновить данные в форме Access.

Объект может реагировать на определенные события, происходящие в процессе работы приложения и влияющие на объект. Совокупность событий, на которые объект способен реагировать, определяется создателем класса, экземпляром которого является данный объект. Например, набор событий, которые определены для формы Access, мы видим на вкладке События (Event) диалогового окна Свойства (Properties). Реакцией объекта на произошедшее событие может быть выполнение объектом некоторой специальной процедуры, которая называется процедурой обработки события. Любому событию объекта может быть назначена некоторая процедура его обработки.

Упорядоченный набор однотипных объектов — экземпляров одного класса называется семейством. Семейство тоже является объектом. Одним из методов этого объекта является процедура, возвращающая ссылку на конкретный объект в семействе. Одним из свойств семейства является число объектов, хранящихся в нем. Например, совокупность элементов управления в форме образует семейство Controls.

Объекты и семейства сгруппированы в виде иерархических структур, которые называются объектными моделями. В VBA определены специальные объектные модели для каждого компонента семейства Microsoft Office и объектные модели, общие для всех компонентов Microsoft Office. Объектные модели VBA можно изучать, используя справочную систему и окно просмотра объектов. Окно просмотра объектов представляет собой специальное средство редактора Visual Basic, позволяющее просматривать содержимое библиотек объектов и производить поиск справочной информации. (Описание окна просмотра объектов можно найти в данной главе, в разд. "Среда программирования Access 2002".)



Отключение



Отключение

Событие Отключение (Deactivate) происходит, когда фокус из формы или отчета переносится на другое окно (таблицы, запроса, формы, отчета, макроса, модуля или окно базы данных). Однако это событие не возникает, когда фокус переходит в диалоговое окно или другое приложение. Событие Отключение (Deactivate) возникает после события Потеря фокуса (LostFocus).



Открытие



Открытие

Событие Открытие (Open) происходит после того, как выполнен запрос, лежащий в основе формы или отчета, но до отображения первой записи или печати отчета. Процедура обработки этого события имеет один параметр — Cancel, при установке которого в значение True отменяется открытие формы или отчета. Обычно процедура обработки события Открытие (Open) используется для проверки условий и предотвращения открытия формы, т. к. следующее по времени событие Загрузка (Load) уже не может быть отменено.



Отмена



Отмена

Событие происходит, когда пользователь отменяет изменения, сделанные в текущем поле или текущей записи, например, нажав клавишу <Esc> или кнопку $$ (Undo Field/Record) на панели инструментов. Процедура обработки этого события имеет один параметр: Cancel. Установив его значение равным True, можно прервать операцию отмены, и тогда данные в текущем поле или записи останутся измененными.



Отсутствие данных



Отсутствие данных

Событие Отсутствие данных (No Data) возникает после форматирования отчета, но до его вывода на печать (до первого события Страница (Page)) и позволяет обнаружить отсутствие записей для отчета, в этом случае печать можно отменить. Процедура обработки данного события имеет один параметр: Cancel, которому следует присвоить значение True, если нужно отменить печать отчета.



Отсутствие в списке



Отсутствие в списке

Событие Отсутствие в списке (NotlnList) возникает в поле со списком, когда пользователь вводит вручную значение в текстовую часть поля, которое отсутствует в списке, и после этого пытается перейти в другое поле или сохранить запись. Для того чтобы данное событие происходило, нужно присвоить свойству Ограничиться списком (LimitToList) значение Yes. Если это свойство имеет значение No, то разрешается ввод в поле данных, не совпадающих ни с одним значением из списка. Процедура обработки настоящего события имеет два параметра: NewData и Response. Параметр NewData содержит введенные данные, a Response управляет обработкой события и может иметь значения 0, 1 или 2. Значение 0 позволяет вывести на экран стандартное сообщение о том, что введенные данные отсутствуют в списке, и запретить ввод. Значение 1 позволяет вместо стандартного сообщения вывести специальное сообщение, например запрашивающее, следует ли сохранить введенное значение. Новые данные при этом не добавляются в список. Значение 2 разрешает добавить новое значение в список. При этом в процедуре обработки данного события нужно добавить значение к источнику строк для поля со списком, после чего поле обновляется, т. к. Access повторно запрашивает источник строк.

Однако, если источником строк для поля со списком является таблица-справочник, простого добавления значения может оказаться недостаточно. Скорее всего, придется вывести специальную форму, в которой пользователь должен будет заполнить все необходимые поля. После сохранения записи в этой форме новые данные добавляются в список. Типичная ситуация, когда требуются такие действия — добавить нового клиента при выписке ему стандартного документа: счета, накладной и т. д.



Содержание главы





Печать



Печать

Событие Печать (Print) возникает после того, как выполнено форматирование раздела отчета, но до того, как он напечатан. Это событие возникает практически после каждого события Форматирование (Format), кроме тех разделов, которые не будут печататься. Так же, как и при форматировании, процедура обработки событий имеет два параметра: Cancel и PrintCount. Cancel позволяет отменить печать текущего раздела или текущей записи в отчете, для чего нужно присвоить ему значение True. Однако при этом остается пустое место на странице, поэтому данную процедуру можно использовать, когда изменения не касаются формата страницы отчета. PrintCount — счетчик, который считает, сколько раз произошло событие Печать (Print).



Переменные, константы и типы данных



Переменные, константы и типы данных

Как и в других языках программирования, в VBA для хранения временных значений, передачи параметров и проведения вычислений используются переменные. Кратко остановимся на основных особенностях описания и использования переменных в VBA.

Обычно перед тем, как использовать переменную, производится ее объявление, т. е. вы заранее сообщаете Visual Basic, какие именно имена переменных вы будете использовать в своей программе, при этом объявляется также тип данных, для хранения которых предназначена эта переменная. В VBA, как и в обычном языке Basic, для этого используется оператор Dim. Вот синтаксис этого оператора:

Dim <имяПеременной> [Аs<типДанных>]

В VBA действуют следующие правила именования переменных. Имя не может быть длиннее 255 символов, оно должно начинаться с буквы, за которой могут следовать буквы, цифры или символ подчеркивания. Оно не должно содержать пробелов, знаков препинания или специальных символов, за исключением самого последнего знака. В конце к имени переменной может быть добавлен еще один из следующих шести специальных символов — описателей типа данных:

! # $ % & @

Эти символы не являются частью имени переменной: если в программе используются одновременно имена stringl$ и stringl, то они ссылаются на одну и ту же строковую переменную. Нельзя использовать одно и то же имя переменной с разными символами определения типа данных или одновременно явное описание типа данных и не соответствующий этому типу данных специальный символ. Мы еще остановимся на этом подробнее при обсуждении типов данных.

Кроме того, не допускается использование в качестве имен переменных ключевых слов VBA и имен стандартных объектов. Именно поэтому рекомендуется начинать имена переменных со строчной, а не с прописной буквы. Поскольку у ключевых слов VBA и имен стандартных объектов первая буква при вводе автоматически преобразуется в прописную, вы будете избавлены от риска нечаянно использовать запрещенное имя переменной.

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

Во многих языках программирования, например в Pascal, переменные должны быть объявлены обязательно, и эти объявления используются компилятором, чтобы зарезервировать память для переменных. В то же время в VBA объявление переменных не яаляется обязательным. Как и в его предшественнике, обычном языке Basic, допускается использование неописанных переменных. Выделение памяти переменным может выполняться динамически, а тип данных, хранящихся в переменной, может определяться по последнему символу имени переменной.

В свое время велись длительные баталии между сторонниками сокращения записи процедур за счет отказа от объявлений переменных и сторонниками обязательного описания всех переменных. Аргументы обеих сторон были достаточно серьезны — действительно, зачастую обязательное описание всех переменных требует изрядной доли занудства при методичном выписывании объявлений типа

Dim i As Integer, j As Integer

Dim x As Double

С другой стороны, трудно что-нибудь возразить и против того, что одним из самых опасных источников труднообнаружимых ошибок в языках программирования, допускающих применение неописанных переменных, служат опечатки в написании имен переменных. Такие опечатки истолковываются транслятором как появление еще одной, новой переменной, отличной от ранее использовавшейся, и не воспринимаются как ошибки. Порой для обнаружения такой опечатки требуется время, во много раз превосходящее то, которое потребовааось бы на явное описание всех используемых в программе переменных.

В VBA принято поистине соломоново решение — предоставить разрешение этой дилеммы самому программисту. В этом языке имеется оператор

Option Explicit

Если вы начнете свой модуль с этого оператора (он должен быть расположен в самом начале модуля, до того, как начнется первая процедура этого модуля), то VBA будет требовать обязательного объявления переменных в этом модуле и генерировать сообщения об ошибке всякий раз, как встретит необъявленную переменную. Кроме того, если вы строгий пуританин и хотели бы, чтобы это требование стало обязательным для всех ваших модулей без исключения, вы можете установить параметр Require Variable Declaration (Явное описание переменных) на вкладке Editor (Редактор) диалогового окна Options (Параметры) редактора VBA. (Подробнее об установке параметров редактора VBA будет рассказано в разд. "Среда программирования Access 2002" ниже в данной главе.)

Установка этого параметра приведет к тому, что редактор Visual Basic будет автоматически добавлять оператор Option Explicit в начало каждого вновь создаваемого модуля. Учтите, однако, что этот флажок не влияет на все ранее созданные модули — если вы хотите добавить этот оператор к уже существующим модулям, вам придется проделать это вручную.

Приведем теперь краткую сводку используемых типов данных VBA (табл. 13.1).



Перемещение указателя



Перемещение указателя

Это событие генерируется непрерывно, когда пользователь перемещает указатель мыши по объектам формы. Пока указатель движется в границах объекта, событие Перемещение указателя (MouseMove) генерируется для данного объекта, когда указатель попадает на пустую область формы, область выделения записи или полосу прокрутки, генерируется событие Перемещение указателя (MouseMove) для формы. Событие возникает также при перемещении формы или элемента управления, например с помощью процедуры VBA, при неподвижном указателе мыши. Процедура обработки события имеет четыре параметра:

Button — определяет состояние кнопок мыши в момент возникновения события (перемещение указателя может происходить при нескольких нажатых или не нажатых кнопках мыши);
Shift — определяет состояние клавиш <Shift>, <Ctrl> и <Alt> в тот момент, когда нажата кнопка, определяемая параметром Button;
X и Y — текущие координаты указателя мыши в типах.



Получение фокуса



Получение фокуса

Событие Получение фокуса (GetFocus) происходит, когда форма или элемент управления формы получают фокус. Элемент управления может получить фокус, только если оно видимо и доступно (его свойства Вывод на экран (Visible) и Доступ (Enabled) имеют значения Да). При этом событие Получение фокуса (GetFocus) происходит после события Вход (Enter). Форма может получить фокус, только если все поля в ней заблокированы, в противном случае событие Получение фокуса (GetFocus) для формы не возникает.



После обновления



После обновления

Событие После обновления (AfterUpdate) происходит после обновления данных в записи или элементе управления. И хотя обновление уже произошло, можно восстановить старые значения, воспользовавшись свойством OldValue элемента управления. Оно сохраняет старое значение элемента управления, которое сменится только после события После обновления (AfterUpdate).

Замечание

События До обновления (BeforeUpdate) и После, обновления (AfterUpdate), а также До вставки (Beforelnsert) и После вставки (Afterlnsert) не возникают, когда значения элементов управления формы изменяются с помощью программы VBA или макрокоманды УстановитьЗначение (SetValue). Кроме того, события До обновления (BeforeUpdate) и После обновления (AfterUpdate)He возникают для вычисляемых элементов управления.

Изменение

Событие Изменение (Change) возникает в следующих случаях:

при изменении содержимого текстового поля или поля со списком, при этом изменением может считаться любой непосредственно введенный или удаляемый символ;
при изменении значения свойства Текст (Text) элемента управления с помощью макроса или процедуры VBA;
в элементе управления Набор вкладок (Tab Control) при переходе с одной вкладки на другую.

Замечание

Событие Изменение (Change) не возникает при изменении значения вычисляемого элемента управления, а также, если с помощью макроса или программы VBA установлено значение текстового поля или поля со списком или если значение поля со списком выбрано из списка.

Некорректная программа обработки данного события может привести к каскадным событиям. Чтобы избежать этого, не следует использовать в настоящей процедуре команды, которые меняют содержимое элемента управления, а также не стоит создавать два и более поля, которые воздействуют друг на друга, например обновляют друг друга.



После подтверждения Del



После подтверждения Del

Событие После подтверждения Del (AfterDelConfirm) происходит как после подтверждения удаления записи, так и при отмене удаления. Процедура обработки данного события имеет один параметр — status, который принимает значения О, 1 или 2 и определяет, была ли удалена запись. Значение 0 указывает, что запись была успешно удалена, 1 означает, что удаление отменено программой обработки события, а значение 2 указывает, что удаление было отменено пользователем в окне подтверждения удаления. Это событие может быть использовано в программе для проверки, была ли удалена запись.



После вставки



После вставки

Событие происходит после того, как в таблицу добавлена новая запись. Обычно это бывает при переходе к следующей записи в форме. Процедура обработки этого события обычно используется для того, чтобы сделать повторный запрос к источнику данных с целью вывода новой записи.



Последовательность событий фокуса...



Последовательность событий фокуса для элементов управления в формах

При установке фокуса на элемент управления щелчком мыши, при нажатии клавиши <Таb> или при открытии формы происходят события: Вход (Enter) => Получение фокуса (GotFocus).

Когда элемент теряет фокус, например при закрытии формы или переносе фокуса на другой элемент управления той же формы, происходят события: Выход (Exit) => Потеря фокуса (LostFocus).

При переносе фокуса в другую форму элемент первой формы теряет фокус, но не возникает события Выход (Exit). Соответственно, когда фокус переносится обратно, т. е. к элементу, который уже имел фокус, когда форма последний раз была активной, то не происходит события Вход (Enter), а только событие Получение фокуса (GotFocus).

Замечание

В дальнейшем при описании последовательностей событий мы не будем приводить английские эквиваленты названий событий, дабы не загромождать представление. Кроме того, вводятся сокращения для обозначения объектов, к которым относится событие, например: э — элемент, ф — форма.

При переносе фокуса из элемента управления в главной форме на элемент управления в подчиненной форме события происходят в следующем порядке: Выход (г.ф., т.ф.) => Потеря фокуса (г.ф., т.ф.) => Вход (г.ф., э.п.) => Выход (п.ф., т.ф.) => Потеря фокуса (п.ф., т.ф.) => Вход "(п.ф., п.ф.) => Получение фокуса (п.ф., п.ф.) Это самая сложная цепочка событий, в которой задействованы сразу четыре элемента управления: г.ф., т.ф. — элемент главной формы, теряющий фокус; г.ф., э.п. — элемент главной формы, содержащий подформу; п.ф., т.ф. — элемент подформы, теряющий фокус (если мы переносим фокус на тот элемент подформы, который до этого фокуса не имел); п.ф., п.ф. — элемент подформы, принимающий фокус. Если перенос фокуса выполняется на элемент подчиненной формы, который имел фокус, когда она последний раз была активной, то в цепочке отсутствуют события: Выход (п.ф., т.ф.) => Потеря фокуса (п.ф., т.ф.) => Вход (п.ф., п.ф.).



Последовательность событий изменения...



Последовательность событий изменения данных в элементе управления

Когда вводят или изменяют данные в элементе управления, а затем переходят к следующему элементу управления, возникает следующая цепочка событий: {Клавиша вниз => Нажатие клавиши => Внесены изменения ==> Изменение => Клавиша вверх}=> До обновления =э После обновления => Выход => Потеря фокуса

Фигурные скобки в приведенном выражении означают, что выделенная цепочка событий возникает при каждом нажатии клавиши на клавиатуре.

Еcли ввод выполняется в поле со списком, то в конец последней цепочки, после события Клавиша вверх, могут добавиться события Отсутствие в списке (NotlnList) и Ошибка (Error), и цепочка будет выглядеть следующим образом: Клавиша вниз => Нажатие клавиши => Внесены изменения => Изменение => Клавиша вверх} => Отсутствие в списке => Ошибка => До обновления => После обновления => Выход => Потеря фокуса



Последовательность событий клавиатуры и мыши



Последовательность событий клавиатуры и мыши

При нажатии и отпускании любой клавиши на клавиатуре в том случае, если фокус находится в одном из элементов управления формы, возникает следующая цепочка событий: Клавиша вниз => Нажатие клавиши => Клавиша вверх

При щелчке мышью на элементе управления формы, соответственно: Кнопка вниз => Кнопка вверх => Нажатие кнопки

Об особенностях этих событий подробно говорилось выше при их описании, поэтому сейчас мы позволим себе не повторяться.



Последовательность событий в формах



Последовательность событий в формах

При открытии формы происходит следующая цепочка событий: Открытие => Загрузка => Изменение размера => Включение => Текущая запись => Вход => Получение фокуса

События Вход (Enter) и Получение фокуса (GetFocus) возникают для первого элемента в первой записи. Если форма не имеет видимых или доступных элементов управления, то последовательность событий несколько иная: Открытие => Загрузка => Изменение размера => Включение => Получение фокуса => Текущая запись

В этом случае событие Получение фокуса (GetFocus) относится к форме. При закрытии формы последовательность событий следующая: Выход => Потеря фокуса => Выгрузка => Отключение => Закрытие

То есть сначала теряет фокус последний элемент в форме, а затем выполняются события для формы. Если в форме не было видимых или доступных элементов, то последовательность другая: Выгрузка => Потеря фокуса (ф) => Отключение => Закрытие

При переключении между двумя открытыми формами последовательность событий следующая: Потеря фокуса (э1) => Отключение (ф!) => Включение (ф2) => Вход (э2) => Получение фокуса (э2)

Если из открытой формы открывают другую форму, то сначала в открываемой форме происходят события Открытие (Open), Загрузка (Load) и Изменение размера (Resize), и только после этого в первой форме произойдет событие Отключение (Deactivate): Открытие (ф2) => Загрузка (ф2) => Изменение размера (ф2) => Отключение (ф1) => Включение (ф2) => Текущая запись (ф2)

Это дает возможность проконтролировать открытие второй формы. Кроме того, событие Включение (Activate) происходит каждый раз, когда форма получает фокус, а события Открытие (Open) и Загрузка (Load) не происходят, если форма уже открыта, даже если переход в эту форму выполняется с помощью макрокоманды ОткрытьФорму (OpenForm). Событие Отключение (Deactivate) для формы не происходит, если фокус переносится в диалоговое окно.

Если открываемая форма содержит подчиненные формы, то сначала загружаются подчиненные формы и осуществляются все события в них, которые обычно происходят при открытии формы, кроме события Включение (Activate) — оно не возникает. Затем загружается главная форма в обычном порядке и для нее выполняется событие Включение (Activate).

Аналогично при закрытии такой формы сначала выгружаются все подчиненные формы, но в них не возникает событие Отключение (Deactivate). События при этом происходят в следующем порядке:

События для элементов подчиненной формы, например Выход (Exit) и Потеря фокуса (LostFocus).
События элементов управления в главной форме, в том числе для того элемента, который содержит подчиненную форму.
События для главной формы.
События для подчиненной формы.



Последовательность событий в форме, связанных с записями



Последовательность событий в форме, связанных с записями

Если просто просматриваются записи в форме, то при переходе к каждой новой записи выполняются событие Текущая запись (Current) для формы и все события, связанные с установкой фокуса в элементах формы. Если данные в записи меняются, то сохранение изменений происходит только при переходе к следующей записи или при закрытии формы (если нашли нужную запись, изменили и закрыли форму). Поскольку все изменения в записи происходят в элементах управления формы, одновременно будут возникать соответствующие события в элементах формы. Рас-смотрим типичную ситуацию, когда в форме выводится запись, в ней перемещаются по элементам управления до нужного элемента, изменяют в нем данные и переходят к следующей записи. В этом случае последовательность возникновения событий будет выглядеть так: Текущая запись (ф) => {Вход (э) => Получение фокуса (э) => Выход (э) => Потеря фокуса (э)} => Вход (э) => Получение фокуса (э) => До обновления (э) => После обновления (э) => До обновления (ф) => После обновления (ф) => Выход (э) => Потеря фокуса (э) => RecordExit => Текущая запись (ф) => Вход (э) => Получение фокуса (э)

В этой цепочке для упрощения опущены все события клавиатуры, а фигурные скобки выделяют цепочки событий, которые возникают при переходе между элементами управления формы. При изменении данных события До обновления (BeforeUpdate) и После обновления (AfterUpdate) происходят сначала для элемента, а затем для формы. Затем последний элемент (в данном случае тот, в котором происходили изменения) теряет фокус, происходит событие RecordExit (Выход из записи), выводится следующая запись, и фокус устанавливается на первый элемент в этой записи. События До обновления (BeforeUpdate) и После обновления (AfterUpdate) всегда возникают непосредственно перед переходом к следующей записи. После этого запись (элемент управления, в котором перед этим находился фокус) теряет фокус.

Замечание

Если запись сохраняется с помощью команды меню Записи, Сохранить запись (Records, Save Record), то последних событий Выход (Exit) и Потеря фокуса (LostFocus) не происходит. Это полезно знать, т. к. иногда требуется обойти эти события.

При удалении записи происходят события: Удаление => До подтверждения Del => После подтверждения Del => Текущая запись => Вход => Получение фокуса

Если событие Удаление (Delete) отменяется, то остальные события не возникают. После удаления записи фокус переходит на следующую запись, поэтому происходят события Текущая запись (Current) формы и Вход (Enter) и Получение фокуса (GetFocus) первого элемента в этой записи.

Добавление новой записи осуществляется после того, как пользователь вводит первый символ новой (пустой) записи. При этом события происходят в следующем порядке: Текущая запись (ф) => Вход (э) => Получение фокуса (э) => До вставки (ф) => Изменение (э) => До обновления (ф) => После обновления (ф) => После вставки (ф)

В этой цепочке пропущены все события клавиатуры и До обновления (BeforeUpdate) и После обновления (AfterUpdate) для элементов формы, т. к. они описаны выше. Событие Изменение (Change) происходит, если первый символ новой записи вводится в текстовое поле.



Последовательность событий в отчетах



Последовательность событий в отчетах

В отчетах события возникают только для самого отчета и его разделов. Для полей отчета события отсутствуют. При выводе отчета на печать события обычно возникают в следующей последовательности: Открытие => Включение => {Формат => Печать} => Закрытие => Отключение

События Форматирование (Format) и Печать (Print) относятся к разделам отчета и возникают при обработке каждого раздела. Дополнительными событиями могут быть события:

Отсутствие данных (NoData), которое возникает перед первым событием Печать (Print), если источник записей не содержит записей.
Страница (Page), которое возникает после всех событий Печать (Print) для страницы отчета.
Событие Возврат (Retreat) возникает в процессе форматировании страницы отчета, когда требуется вернуться к предыдущему разделу, перед событиями Печать (Print) для страницы.



Последовательности событий Access



Последовательности событий Access

При написании процедур обработки событий очень важно понимать, в каком порядке они происходят, т. к. приложение Access управляется событиями и результат работы зависит от того, в каком порядке эти процедуры будут выполняться. В данном разделе мы опишем порядок возникновения событий в формах и отчетах.



Потеря фокуса



Потеря фокуса

Событие Потеря фокуса (LostFocus) происходит каждый раз, когда форма или элемент управления в форме теряют фокус. Событие происходит после события Выход (Exit).

Замечание

События Получение фокуса (GetFocus) и Потеря фокуса (LostFocus) происходят не только, когда фокус перемещается путем действий пользователя (с помощью клавиатуры или мыши), но и в результате вызова метода SetFocus объекта в форме или выполнения макрокоманд

ВыделитьОбъект(SelectObject), НаЗапись(GoToRecord), КЭлементуУправления(GoToControl) и НаСтраницу(GoToPage).

Кроме того, эти события определены для элементов (флажков и переключателей) внутри группы.



При обновлении



При обновлении

Событие При обновлении (Updated) возникает при изменении объекта OLE и применяется только к свободным и присоединенным рамкам объекта.

Процедура обработки данного события используется для проверки, были ли данные в объекте OLE изменены после последнего сохранения. Процедура имеет один параметр — Code, который указывает, каким образом обновлялся объект, и может иметь значения 0, 1, 2 и 3. Значение 0 указывает, что данные объекта изменены. Значение 1 указывает, что данные объекта сохранялись приложением, создавшим объект. Значение 2 указывает, что файл объекта OLE закрывался приложением, которое его создало. Значение 3 указывает, что файл объекта OLE переименован создавшим его приложением.



Применение фильтра



Применение фильтра

Событие Применение фильтра (ApplyFilter) возникает во всех случаях, когда пользователь выполняет фильтрацию записей в форме с помощью соответствующих команд меню, контекстного меню или кнопки панели инструментов (применить или удалить фильтр). Программу обработки этого события обычно используют либо для проверки условия в фильтре, либо для изменения вида формы перед применением фильтра, если требуется скрыть лишние поля или, наоборот, показать скрытые. Программа обработки события имеет два параметра — Cancel и ApplyType. Cancel позволяет отменить операцию фильтрации, если, например, условие сформулировано неправильно, для чего нужно присвоить ему значение True. ApplyType определяет исполняемое действие и может принимать значения 0, 1 и 2. Значение 0 указывает на удаление фильтра, 1 — на применение фильтра, 2 — на закрытие окна фильтра.

Замечание

Событие не возникает при выполнении операций фильтрации с помощью макрокоманд ПрименитьФильтр(ApplyFilter) , ОткрытьФорму(OpenForm), ПоказатьВсеЗаписи (ShowAllRecords), соответствующих им методов объекта DoCmd, или при закрытии окна фильтра (любого) с помощью макрокоманды Закрыть(Close).



Процедуры и функции, их вызов и передача параметров



Процедуры и функции, их вызов и передача параметров

Основными компонентами программы на VBA являются процедуры и функции, Они представляют собой фрагменты программного кода, заключенные между операторами Sub и End Sub или между операторами Function и End Function. Вот как может выглядеть процедура VBA:

Sub <имяПроцедуры> (<аргумент1>, <аргумент2>, ... )

<onepaтopVisualBasic1> <onepaтopVisualBasic2>

End Sub

Функция отличается от процедуры тем, что ее имя выступает также в качестве переменной и используется для возвращения значения в точку вызова функции. Вот как может выглядеть функция:

F unction <имяФункции> (<аргумент1>, <аргумент2>, ... )

<onepaторVisualBasicl> <onepaторVisualBasic2>

<имяФункции> = <возвращаемоеЗначение>

End Function

Для того чтобы использовать написанную вами процедуру или функцию, необходимо вызвать ее. Как же осуществляется вызов процедур и функций? Процедуру с непустым списком аргументов можно вызвать только из другой процедуры или функции, использовав ее имя со списком фактических значений аргументов в качестве одного из операторов VBA. Функцию же можно вызвать не только с помощью отдельного оператора VBA, но и поместив ее имя со списком фактических значений аргументов прямо в формулу или выражение в программе на VBA или, например, прямо в формулу в вычисляемых полях запросов, форм и отчетов Access. Процедура с пустым списком аргументов (так называемый командный макрос) может быть вызвана не только из другой процедуры или функции, но и с помощью комбинации клавиш быстрого вызова, команд раскрывающихся меню или кнопок панелей инструментов. Можно также связать такую процедуру с выполнением самых различных событий: например, с открытием формы или отчета, со щелчком мышью по кнопке в форме, с воздействием на элементы управления форм, в частности элементы управления ActiveX. Такие процедуры называют процедурами обработки событий. Понятно, что функции или процедуры, нуждающиеся в передаче им аргументов, таким способом вызвать нельзя. Подробнее о том, как создаются процедуры обработки событий, будет рассказано в разд. "Программирование в формах и отчетах" данной главы.

Если вызываемая процедура имеет уникальное имя и находится в том же модуле, что и вызывающая процедура, то для ее вызова достаточно указать это имя и задать список фактических значений аргументов, не заключая его в скобки. Второй способ вызова процедуры состоит в использовании оператора Call. Сначала идет оператор Call, затем имя процедуры и список параметров, в этом случае обязательно заключенный в скобки. Функцию можно вызывать точно так же, как и процедуру, но гораздо чаще используется другой, специфический способ вызова функций: использованием ее имени с заключенным в скобки списком параметров в правой части оператора присваивания.

Вот примеры вызова процедуры под именем CrossRC с передачей ей двух аргументов (константы и выражения):

CrossRC 7, i + 2

ИЛИ

Call CrossRC(7, i + 2)

А вот пример вызова двух функций — Left и Mid, и использования возвращаемого ими значения в выражении:

yStr = Left(y, 1) & Mid(у, 2, 1)

Допускается два различных способа передачи переменных процедуре или функции: по ссылке и по значению. Если переменная передается по ссылке, то это означает, что процедуре или функции будет передан адрес этой переменной в памяти. При этом происходит отождествление формального аргумента процедуры и переданного ей фактического параметра. Тем самым вызываемая процедура может изменить значение фактического параметра: если будет изменен формальный аргумент процедуры, то это скажется на значении переданного ей при вызове фактического параметра. Если же фактический параметр передается по значению, то формальный аргумент вызываемой процедуры или функции получает только значение фактического параметра, но не саму переменную, используемую в качестве этого параметра. Тем самым все изменения значения формального аргумента не сказываются на значении переменной, являющейся фактическим параметром.

Способ передачи параметров процедуре или функции указывается при описании ее аргументов: имени аргумента может предшествовать явный описатель способа передачи. Описатель ByRef задает передачу по ссылке, a ByVal — по значению. Если же явное указание способа передачи параметра отсутствует, то по умолчанию подразумевается передача по ссылке.

Поясним сказанное на примере. Пусть имеются следующие описания двух процедур:

Sub Main()

а = 10

b = 20

с = 30

Call Examplel(a, b, с)

Call MsgBox(a)

Call MsgBox(b)

Call MsgBox(c)

End Sub

Sub Example1(x, ByVal y, ByRef z)

x = x + 1

у = у + 1

z = z + 1

Call MsgBox(x)

Call MsgBox(y)

Call MsgBox(z)

End Sub

Вспомогательная процедура Examplel использует в качестве формальных аргументов три переменные, описанные по-разному. Далее в теле этой процедуры каждый из них увеличивается на единицу, а затем их значения выводятся на экран с помощью функции MsgBox. Основная процедура Main устанавливает значения переменных a, b и с, а затем передает их в качестве (фактических) аргументов процедуре Examplel. При этом первый аргумент передается по ссылке (действует умолчание), второй — по значению, а третий — снова по ссылке. После возврата из процедуры Examplel основная процедура также выводит на экран значения трех переменных, передававшихся в качестве аргументов. Всего на экран выводится шесть значений:

сначала это числа 11, 21 и 31 (все полученные значения увеличены на 1 и выводятся процедурой Examplel);
затем это числа 11, 20 и 31 (эти значения выводятся процедурой Main, причем переменные, переданные по ссылке, увеличились, а переменная, переданная по значению — нет).

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

Каждая из процедур, находящихся в одном модуле, должна иметь уникальное имя, однако в проекте может содержаться несколько различных модулей. Обычно рекомендуется использовать только уникальные имена процедур в одном проекте, но допустимы и исключения. В том случае, если в проекте содержится несколько различных процедур с одним и тем же именем, необходимо для уточнения имени использовать при вызове процедуры следующий синтаксис:

<имяМодуля>.<имяПроцедуры>

Если при этом имя модуля состоит из нескольких слов, следует заключить это имя в квадратные скобки. Например, если модуль называется "Графические процедуры", а процедура — "Крестик", вызов может выглядеть следующим образом:

[Графические процедуры].Крестик

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

<имяПроекта>.<имяМодуля>.<имяПроцедуры>



Данная глава посвящена основному средству



Глава 13.

Программирование в Access 2002

Данная глава посвящена основному средству программирования в Access 2002 — языку программирования Visual Basic for Applications (VBA). Язык программирования VBA является общим инструментом для всех приложений Microsoft Office, позволяющим решать любые задачи программирования, начиная от автоматизации действий конкретного пользователя и кончая разработкой полномасштабных приложений, использующих Microsoft Office в качестве среды разработки.

Цель этой главы — дать читателю основные сведения как о самом языке, так и о тех инструментальных средствах, которые предоставляет разработчику приложений среда Access 2002.

Поскольку Visual Basic for Applications является объектно-ориентированным языком программирования, будут описаны объектные модели, которые могут использоваться в Access 2002. Это не только собственная объектная модель Access, но и объектные модели Visual Basic for Applications и Microsoft Office, которые являются общими для всех приложений семейства. Основная работа в приложениях Access — это работа с данными, поэтому будут рассмотрены также библиотеки управления данными: DАО (Data Access Objects), ADO (ActiveX Data Objects), JRO (Jet and Replication Objects).

Модель программирования в Access является событийно-управляемой, т. е. в процессе работы приложения возникают события, которые запускают специальные программы — обработчики событий. Большое количество разнообразных событий определено в таких объектах Access, как формы, отчеты и элементы управления в них. Мы подробно описываем эти события и последовательности их возникновения, т. к. искусство программирования в формах и отчетах включает в себя правильное определение того события, которое требуется обработать специальной программой.

Итак, в данной главе будут рассмотрены следующие вопросы:

Синтаксис языка Visual Basic for Applications
Интегрированная среда VBA, которая включает в себя как редактор кода программных модулей, так и большое количество средств отладки этого кода
Объектные модели, применяемые в приложениях Access
События форм, отчетов и элементов управления и последовательности их возникновения
Примеры применения процедур обработки событий в формах и отчетах


Программирование в формах и отчетах


Программирование в формах и отчетах, как правило, составляет большую часть кода приложения, т. к. именно формы и отчеты являются основой интерфейса пользователя и с помощью программирования этот интерфейс гибко настраивается нужным образом. Основой для программирования в формах и отчетах является множество событий, обрабатывающихся специальными процедурами. О создании таких процедур, а также использовании макросов для обработки событий мы уже говорили выше (см. разд. "Применение макросов" гл. 11).

В данном разделе мы хотим сделать обзор этих событий и описать последовательность их возникновения с тем, чтобы читатель мог их правильно использовать.

Помимо процедур обработки событий, программирование может применяться для динамического (то есть в процессе работы приложения) изменения свойств форм, отчетов и элементов управления.



Проверка дублирования значений первичного ключа



Проверка дублирования значений первичного ключа

Обычно проверка дублирования значений первичного ключа задается на уровне таблицы, т. е. когда вы определили поле в таблице как первичный ключ, значение свойства Индексированное поле (Indexed) автоматически устанавливается равным Yes (No Duplicates) — Да (Совпадения не допускаются). Однако эта проверка выполняется только тогда, когда запись сохраняется в базе данных. Если значение ключевого поля вводится в форме пользователем, как, например, в таблице "Клиенты" (Customers), то эту проверку лучше выполнить сразу после ввода данных в это поле. Наиболее подходящим событием для этого является событие До изменения (Before Update). В форме "Клиенты" (Customers) элемент управления "КодКлиента (CustomerID) содержит идентификатор клиента. Событие До изменения (Before Update) этого поля обрабатывается с помощью макроса "Клиенты" (Customers.ValidateID), который выполняет необходимую проверку. Мы покажем, как можно обработать это событие с помощью процедуры VBA. Данная процедура может глядеть следующим образом.

Private Sub КодКлиента_ВеforeUpdate (Cancel As Integer)

Dim rs As Recordset

Set rs = CurrentDB.Openrecordset("Клиенты", dbOpenTable)

rs.Index = "PrimaryKey"

rs.Seek "=", Me!КодКлиента

if Not rs.NoMatch Then

MsgBox "Клиент с таким идентификатором уже существует в базе"

Cancel = True

End If

rs .Close

End Sub

Поиск записи со значением ключа, совпадающим с введенным значением поля "КодКлиента" (CustomerlD), выполняется с помощью метода Seek объекта Recordset. Этот метод обеспечивает быстрый поиск необходимой записи. Применить его можно только к набору записей табличного типа, поэтому при создании этого набора записей используется внутренняя константа dbOpenTable. Если такая запись найдена, свойство NoMatch объекта Recordset принимает значение False. В этом случае процедура выведет сообщение, что такой пользователь уже существует и присвоит значение True аргументу Cancel. Это позволяет отменить обновление значения элемента управления. Если значение свойства NoMatch объекта Recordset равно True, процедура закрывает набор записей (рекомендуется не забывать это делать) и завершает свою работу.



Работа с объектами в семействах



Работа с объектами в семействах

Доступ к объектам, входящим в семейство, в большинстве случаев возможен только через упоминание имени семейства, поэтому в программах VBA приходится выполнять различные операции с семействами. Например иногда, чтобы обратиться к объекту в семействе, нужно перебрать несколько или даже все объекты семейства. Допустим, требуется проверить, открыта ли определенная форма в нашем приложении. Для этого мы можем написать функцию, которая должна проверить, входит ли эта форма в семейство Forms. При этом функция может иметь следующий вид:

Function IsLoaded (strFormName As String) As Boolean

'Возвращает значение True, если форма открыта и False, если нет

Dim frm As Form

IsLoaded = False

For each frm in Forms

If frm.Name = FormName

Then IsLoaded = True

Exit Function

EndIf

Next frm

End Function

В данной функции мы сначала объявили объектную переменную типа Form и установили начальное значение функции. Затем мы организуем цикл, в котором перебираем элементы семейства Forms до тех пор, пока не обнаружим в нем объект Form с именем, совпадающим со строковой переменной, которая является аргументом функции. Если такой объект найден, мы присваиваем функции значение True и выходим из нее. Если нет, то когда будут перебраны все элементы семейства Forms, функция вернет значение False.

Для того чтобы организовать цикл с перебором элементов, количество которых неизвестно, в настоящем примере мы использовали оператор For Each. . .Next. Этот оператор обычно используется при работе с семействами. Однако мы могли организовать такой же цикл, используя обычный оператор For. . .Next, т. к. любое семейство (в том числе и Forms) имеет свойство Count, которое возвращает количество элементов в семействе. Ниже приводится другой вариант организации этого цикла:

For I = 0 То Forms.Count - 1

If frm(I).Name = FormName Then

IsLoaded = True

Exit Function

EndIf

Next I

Кроме указанного свойства, семейства объектов доступа к данным имеют два метода, которые позволяют добавлять объекты в семейство и удалять их из семейства, — методы Append и Delete. Это обеспечивает оперативное создание объектов доступа к данным, например, временных таблиц. Чтобы создать таблицу программным путем, вы должны не только определить эту таблицу, но и добавить ее в соответствующее семейство. Ниже приводится фрагмент кода процедуры, в котором создается новая таблица, определяются два ее поля и добавляются объекты в семейства Fields и TableDef s

'Объявляем объектные переменные для объектов:

база данных, таблица и поле Dim db As Database,

td As TableDef, fid As Field

'Устанавливаем ссылку на текущую базу данных

Set db = CurrentDb

'Создаем новую таблицу, используя метод

CreateTableDef объекта Database

Set td = db.CreateTableDef("Временная")

'Создаем поле в таблице, используя метод

CreateField объекта TableDef

'Поле будет иметь имя "Дата" и тип Дата/время

Set fid = td.CreateField("Дата",dbDate)

'Добавляем поле "Дата" в семейство Fielfs таблицы

td.Fields.Append fid

'Создаем второе поле с именем "Сумма" и типом Денежный

Set fid = td.CreateField("Сумма",dbCurrency)

'Добавляем поле "Сумма" в семейство Fielfs таблицы

td.Fields.Append fid

'Добавляем таблицу к семейству TableDefs базы данных

db.TableDefs.Append td

'Обновляем семейство TableDefs

db.TableDefs.Refresh

Яосле выполнения этой программы на вкладке Таблицы (Tables) окна базы данных появится новая таблица "Временная".

Удалить эту таблицу можно аналогичным способом, только уже воспользовавшись методом Delete семейства TableDefs.

db.TableDefs.Delete "Временная"

db.TableDefs.Refresh

Set db = Nothing

Метод Refresh обновляет количество объектов семейства после добавления или удаления объектов. В последнем предложении мы освобождаем объектную переменную db.

Замечание

К сожалению, семейства в модели Microsoft Access не имеют аналогичных методов. Это означает, что вы не можете, например, оперативно добавлять или удалять поля в формах или отчетах. Если в зависимости от условий в форме должны отображаться или не отображаться некоторые поля, приходится создавать элементы управления для всех возможных полей, а затем использовать свойство Visible соответствующих элементов управления, чтобы поля либо были видимы, либо невидимы. В семействах объектной модели Microsoft Office аналогичные свойства есть: Add и Delete. Это позволяет оперативно управлять, например, кнопками на панелях команд.



Первый уровень иерархии...



Рис. 13.1. Первый уровень иерархии объектной модели Microsoft Access 2002



Второй уровень иерархии...



Рис. 13.2. Второй уровень иерархии объектной модели Microsoft Access 2002 — объекты баз данных



Второй уровень иерархии...



Рис. 13.3. Второй уровень иерархии объектной модели Microsoft Access 2002 — объекты для работы с базой данных и проектом

Глядя на схемы объектной модели, можно определить какие объекты описывают приложение, как они связаны между собой и как составить ссылку для доступа к конкретному объекту.

Табл. 13.3 содержит описание объектов Microsoft Access 2002, определенных в библиотеке Access, если не указана другая библиотека объектов.



Модель объектов доступа...



Рис. 13.4. Модель объектов доступа к данным для рабочей области Microsoft Jet

В табл. 13.4 описаны объекты доступа к данным. В первом столбце приведены объекты-семейства, а во втором — объекты, являющиеся элементами соответствующего семейства, в третьем — описание объекта. В последующих главах книги "вы встретитесь с примерами использования объектной модели DAO.



Модель объектов доступа...



Рис. 13.5. Модель объектов доступа к данным для рабочей области ODBCDirect