| « Поставить закладку » « Сделать стартовой » | |||
|
|||
|
Глава 13. Программирование в Access 2002.
Глава 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 для приложений
(VBA) Следующие ниже
подразделы данного раздела описывают синтаксис языка программирования
VBA. Процедуры и функции, их вызов и передача
параметров Основными
компонентами программы на VBA являются процедуры и функции, Они
представляют собой фрагменты программного кода, заключенные между операторами
Sub и End Sub или между операторами Function и End Function. Вот как может
выглядеть процедура VBA: Sub <имяПроцедуры> (<аргумент1>, <аргумент2>, ... ) <onepaTopVisualBasic1> <onepaTopVisualBasic2> End
Sub Функция
отличается от процедуры тем, что ее имя выступает также в качестве переменной и
используется для возвращения значения в точку вызова функции. Вот как может
выглядеть функция: Function <имяФункции> (<аргумент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
основная процедура также выводит на экран значения трех переменных,
передававшихся в качестве аргументов. Всего на экран выводится шесть
значений:
Программа может
состоять (и обычно состоит) из многих процедур и функций, которые могут
располагаться в одном или нескольких модулях. Модули группируются в
проекты, при этом в одном проекте могут мирно сосуществовать несколько
различных программ, использующих общие модули или процедуры. Каждая из
процедур, находящихся в одном модуле, должна иметь уникальное имя, однако в
проекте может содержаться несколько различных модулей. Обычно рекомендуется
использовать только уникальные имена процедур в одном проекте, но допустимы и
исключения. В том случае, если в проекте содержится несколько различных процедур
с одним и тем же именем, необходимо для уточнения имени использовать при вызове
процедуры следующий синтаксис: <имяМодуля>.<имяПроцедуры> Если при этом
имя модуля состоит из нескольких слов, следует заключить это имя в квадратные
скобки. Например, если модуль называется "Графические процедуры", а процедура —
"Крестик", вызов может выглядеть следующим образом: [Графические
процедуры].Крестик Допускается
также использование процедур, расположенных и в других проектах. При этом может
потребоваться еще один уровень уточнения имени: <имяПроекта>.<имяМодуля>.<имяПроцедуры> Переменные, константы и типы данных Как и в других
языках программирования, в 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). Таблица
13.1. Типы данных VBA
При описании
переменной указание типа данных может быть опущено. Тип переменной в таком
случае определяется последним символом имени переменной: @, #, %, &, ! или $
(Currency, Double, Integer, Long, Single или String соответственно). Например,
поскольку символ "$" является символом определения типа для строковых данных, то
переменная под именем text$ автоматически становится переменной типа "строка
символов". В дальнейшем этот специальный символ указания типа данных может быть
опущен, однако постоянное присутствие в имени переменной символа определения
типа будет напоминать о том, к какому типу данных относится эта переменная, что
поможет избежать ошибок использования несовместных типов данных. Если же
последний символ не является ни одним из вышеперечисленных и явное указание типа
тоже не используется, в этом случае переменной будет назначен по умолчанию тип
данных Variant, который позволяет хранить в ней данные любого
типа. Учтите также,
что нельзя использовать в одной и той же процедуре имена переменных,
отличающиеся друг от друга только специальным символом определения типа в конце
переменной. Например, не допускается одновременное использование переменных var$
и var%. He допускается и явное объявление переменной, уже содержащей символ определения типа в
конце имени, с помощью описателя As <типПеременной> (даже если такое
определение не противоречит обычному применению символа определения типа). Так,
например, вы получите сообщение об ошибке, попытавшись ввести любое из следующих
определений: Dim varl% As String Dim var2% As
Integer Для определения
типа данных аргументов процедуры или функции используется описание типа данных
непосредственно в заглавной строке процедуры или функции. Например, следующая
заглавная строка процедуры описывает ее параметры как переменные строкового
типа: Sub SplitStr(str1 As String, str2 As String, str3 As String) Определение типа
данных возвращаемого функцией значения завершает заглавную строку функции,
например: Function FindSplitSpace (strl As String) As
Integer описывает
возвращаемое функцией значение как переменную короткого целого
типа. Чтобы программа
работала быстрее и занимала меньше памяти, рекомендуется использовать, когда это
возможно, конкретные типы переменных, а не универсальный тип Variant. На
обработку переменных типа Variant требуется не только дополнительная память
(сравните размеры, приведенные в табл. 13.1), но и дополнительное время:
требуется выяснить, к какому конкретному типу данных принадлежит такая
переменная в момент обработки, а также при необходимости выполнить
преобразование данных к нужному типу. Может показаться, что в таком случае лучше
вообще не использовать подобные переменные. Это не так. Часто подобные
переменные просто необходимы: например, в том случае, когда вы точно не уверены,
какие именно данные будут присвоены переменной. Приведем здесь
лишь один пример. Если вы хотите, чтобы пользователь программы ввел некоторое
целое значение, необходимое для дальнейшей работы программы, и описали для этого
переменную целого типа, то рекомендуется использовать для ввода данных
промежуточную переменную, описанную как Variant, а затем выполнить присваивание
введенного значения нужной переменной (или же описать переменную, в которую вы
хотите поместить это значение как Variant, несмотря на то, что ввести
предполагается именно целое число). Дело в том, что пользователь может ошибиться
и ввести, например, вещественное число или вообще нечаянно нажать не на ту
клавишу и ввести строковое значение. В таком случае при присваивании введенного
значения переменной целого типа произойдет ошибка во время выполнения программы.
Если же переменная для ввода будет объявлена как Variant, ничего страшного не
случится: введенное значение будет благополучно присвоено этой переменной, а вы
получите возможность проанализировать введенное значение и попросить
пользователя повторить ввод, если введенное им значение не отвечает нужным
условиям. И в завершение
этого раздела обсудим использование именованных констант. Для их описания
применяется оператор Const, схожий с оператором описания переменных Dim. Вот
синтаксис этого оператора: Const <имяКонстанты> [As
<типДанных>] = <выражение> где
<выражение> — эго любое значение или формула, возвращающая значение,
которое должно использоваться в качестве константы. Например, следующий оператор
определяет целую константу maxLen: Const maxLen% =
30 Как и
переменные, константы могут содержать значения различных типов данных, но при
этом они не меняют своих значений во время выполнения программы. Совет
Кроме
описываемых пользователем констант, существуют еще предопределенные встроенные
константы, которые включаются в тексты программ без предварительного описания.
Сведения о предопределенных встроенных константах, используемых для различных
объектов приложений Microsoft Office и Visual Basic, можно найти в справке—в
разделах описания свойств объектов (реже — в разделах описания методов). При
именовании встроенных констант используется стандартное соглашение, позволяющее
определить, к объектам какого приложения относится эта константа. Например,
встроенные константы, относящиеся к объектам Access, начинаются с префикса ас,
относящиеся к объектам Excel — с префикса xl, относящиеся к объектам Word — с
префикса wd, а относящиеся к объектам VBA — с префикса vb. Например, в
команде DoCmd.OpenForm "Orders", acNormal, , stLinkCriteria используется
встроенная константа Access acNormal. Кроме обычных
переменных, в Visual Basic часто встречаются неременные, представляющие собой
ссылку на объект. Оказывается, зачастую использование переменных для ссылок на
объекты позволяет не только сократить и упростить текст программы, но и
существенно ускорить ее работу. Применение
переменной-объекта отличается от использования обычных переменных: нужно не
только объявить такую переменную, но и назначить ей соответствующий объект с
помощью специального оператора Set. Вот синтаксис этого объявления и
назначения: Dim
<имяПеременкой> As Object Set
<имяПеременной> = <ссылкаНаОбъект> Иногда при
объявлении такой переменной удобно заранее указать конкретный тип объекта —
можно использовать любой конкретный объект из объектной модели Office. Приведем
пример упомянутого объявления и назначения: Dim MyBase As Database Set MyBase =
CurrentDb( ) После такого
объявления и назначения вы можете применять переменную MyBase для обращения к
текущей открытой базе данных. Мало того, что такая ссылка короче: она еще и
быстрее обрабатывается, и программа, использующая переменные для прямых ссылок
на объекты вместо сложных иерархических ссылок, включающих в себя большое
количество операторов уточнения (точек), работает быстрее. Время, которое уходит
у программы на разрешение ссылок, пропорционально количеству операторов
уточнения, которые приходится обрабатывать программе. Совет Еще одно
замечание о быстродействии. Если вы всерьез озабочены быстродействием вашей
программы, то рекомендуется при описании переменных типа "объект" использовать
конкретные объекты модели Office, а не универсальное описание Object. В
оправдание можно привести примерно те же соображения, что и по поводу применения
универсального типа Variant при описании обычных переменных: обработка такого
типа переменных требует дополнительного времени и места в
памяти. Объектная
переменная будет указывать на объект до тех пор, пока мы другим оператором Set
не присвоим ей ссылку на другой объект этого же типа или не присвоим ей значение
Nothing, что означает, что переменная не содержит никакой ссылки.
Например: Set txt =
Nothing После такого
действия переменная продолжает существовать, хотя и не ссылается ни на какой
объект. Другим оператором Set ей можно снова присвоить ссылку на
объект. Замечание
Массив —
это переменная, в которой хранится одновременно несколько значений
одинакового типа. Формальное определение массива таково: он представляет собой
совокупность однотипных индексированных переменных. Количество
используемых индексов массива также может быть различным. Чаще всего применяются
массивы с одним или двумя индексами, реже — с тремя, еще большее количество
индексов встречается крайне редко. В VBA допускается использовать до 60
индексов. О количестве индексов массива обычно говорят как о размерности
массива. Массивы с одним индексом называют одномерным, с двумя — двумерными и т.
д. Массивы с большим количеством измерений могут занимать очень большие объемы
памяти, так что следует быть осторожным в их применении. Прежде чем
использовать массив, нужно обязательно объявить его с помощью оператора Dim и
указать при этом тип хранящихся в массиве значений. Все значения в массиве
обязаны принадлежать к одному типу данных. Это ограничение на практике можно
обойти, использовав при объявлении массива тип Variant — в этом случае элементы
массива смогут принимать значения разных типов. Вот синтаксис оператора
объявления массива: Dim
<имяМассива> (<размер1>, <размер2>, ...) As
<типДанных> где указанные в
скобках величины <размер!>, <размер2> и т.д. задают размеры массива
— количество индексов и максимально допустимое значение для каждого. конкретного
индекса. При этом индексирование элементов массива по умолчанию начинается с
нуля. Так, объявление Dim Arrayl (9) As
Integer определяет
одномерный массив из 10 элементов, являющихся переменными целого типа, а
объявление Dim Array2 (4, 9)
As Variant определяет
двумерный массив из пятидесяти (5x10) элементов, являющихся переменными
универсального типа variant. Замечание
При объявлении
массива можно указать не только верхнюю границу индекса, но и его нижнюю
границу, т. е. явно задать диапазон изменения конкретного индекса массива,
причем нижняя граница может быть любым целым числом, необязательно
неотрицательным. Вот синтаксис такого определения: 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) =
"Строка!" В этом примере
массив dArray сначала определяется как двумерный массив из шести элементов, а
затем переопределяется как одномерный массив, причем верхняя граница индекса
задается значением переменной k. Замечание
Учтите, что по
умолчанию при изменении размеров массива ему заново выделяется память и текущие
значения его элементов теряются. Чтобы не потерять текущие значения массива при
изменении его размеров, используется ключевое слово Preserve. Например, чтобы
увеличить размер массива dArray на один элемент, не потеряв значений
существующих элементов, можно поступить следующим образом: ReDim Preserve
dArray (UBound( dArray) + 1) Область действия переменных и процедур Все процедуры,
функции, переменные и константы в 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. Как и во всех
других языках программирования, в VBA имеются различные управляющие конструкции,
позволяющие изменять порядок выполнения программы. Если управляющие конструкции
не используются, происходит последовательное выполнение операторов языка
программирования, начиная с самого первого и кончая последним. Хотя в некоторых
самых простых случаях этого и бывает достаточно, обычно все-таки требуется
изменять порядок исполнения операторов при выполнении определенных условий, либо
пропуская выполнение некоторых операторов, либо, наоборот, многократно повторяя
их. Оказывается, для реализации любых алгоритмов достаточно иметь только два
вида конструкций управления: ветвления и циклы. Управляющие
конструкции ветвления позволяют проверить некоторое условие и, в зависимости от
результатов этой проверки, выполнить ту или иную группу операторов. Для
организации ветвлений в VBA используются различные формы оператора ветвления If
и-оператор выбора Select Case. Простейшая,
краткая форма оператора if используется для проверки одного условия, а затем
либо выполнения, либо пропуска одного оператора или блока из не- скольких
операторов. Краткая форма оператора ветвления if может иметь как однострочную,
так и блочную форму. В одну строку краткая форма If может быть записана
так: If <условие>
Then <оператор> В блочной форме
краткое ветвление выглядит следующим образом: If <условие> Then <оператор1> <оператор2> End
If В качестве
условия можно использовать логическое выражение, возвращающее значение True или
False, или любое арифметическое выражение. Если применяется арифметическое
выражение, то нулевое значение этого выражения эквивалентно логическому значению
False, а любое ненулевое выражение эквивалентно True. В том случае, когда
условие возвращает значение False, оператор или блок операторов, заключенных
между ключевыми словами Then и End if и составляющих тело краткого оператора
ветвления, не будет выполняться. Замечание
Полная форма
оператора if используется в тех случаях, когда имеются два различных блока
операторов и по результатам проверки условия нужно выполнить один из них. Такая
форма if не может записываться в одну строку и всегда имеет блочную форму
записи: If <условие>
Then <блокОператоров1> Else <блокОператоров2> End
If Если условие
истинно, выполняется первый блок операторов, заключенный между ключевыми словами
Then и Else, а в противном случае — второй блок, заключенный между ключевыми
словами Else и End If. Совет
Иногда
приходится делать выбор одного действия из целой группы действий на основе
проверки нескольких различных условий. Для этого можно использовать цепочку
операторов ветвления If. . .Then. . . Elseif: If <условие1>
Then <блокОператоров!> Elseif
<условие2> Then <блокОператоров2> Elseif
<условие3> Then <блокОператоровЗ> Elseif
<условиеN> Then <блокОператоровN> Else <блокОператоров_Еlsе> End If Такие цепочки
операторов If.. .Then. . .Elseif обладают большой гибкостью и позволяют решить
все проблемы, однако если выбор одной из нескольких возможностей все время
основан на различных значениях одного и того же выражения, гораздо удобнее
использовать специально предназначенный для этого оператор выбора Select Case,
имеющий следующий синтаксис: Select Case <проверяемоеВыражение> Case
<списокЗначений1> <блокОператоров1> Case
<списокЗначений2> <блокОператоров2> Case
<списокЗначенийЗ> <блокОператоровЗ> Case
Else <блокОператоровЕlsе> End
Select Проверяемое
выражение вычисляется в начале работы оператора Select Case. Это выражение может
возвращать значение любого типа, например логическое, числовое или
строковое. Список выражений
представляет собой одно или несколько выражений, разделенных запятой. При
выполнении оператора проверяется, соответствует ли хотя бы один из элементов
этого списка проверяемому выражению. Эти элементы списка выражений могут иметь одну из следующих форм:
Если хотя бы
один из элементов списка соответствует проверяемому выражению, то выполняется
соответствующая группа операторов и на этом выполнение оператора Select Case
заканчивается, а остальные списки выражений не проверяются, т. е. отыскивается
только первый подходящий элемент списков выражений. Если же ни один из элементов
всех этих списков не соответствует значению проверяемого выражения, выполняются
операторы группы Else, если таковая присутствует. В VBA имеется
богатый выбор средств организации циклов, которые можно разделить на две
основные группы — циклы с условием Do... Loop и циклы с перечислением
For...Next. Циклы типа Do
... Loop используются в тех случаях, когда заранее неизвестно, сколько раз
должно быть повторено выполнение блока операторов, составляющего тело цикла.
Такой цикл продолжает свою работу до тех пор, пока не будет выполнено
определенное условие. Существуют четыре вида циклов Do...Loop, которые
различаются типом проверяемого условия и временем выполнения этой проверки. В
табл. 13.2 приводится синтаксис этих четырех конструкций. Таблица
13.2. Синтаксис операторов цикла Do
Имеется также
две разновидности оператора цикла с перечислением For. . .Next. Очень часто при
обработке массивов, а также в тех случаях, когда требуется повторить выполнение
некоторой группы операторов заданное число раз, используется цикл For. .
.Next со счетчиком. В отличие от циклов Do. . .Loop, данный тип цикла
использует специальную переменную, называемую счетчиком, значение которой
увеличивается или уменьшается при каждом выполнении тела цикла на определенную
величину. Когда значение этой переменной достигает заданного значения,
выполнение цикла заканчивается. Синтаксис этого
вида цикла выглядит, следующим образом (в квадратные скобки заключены
необязательные элементы синтаксической конструкции): For <счетчик> = <начальноеЗначение> То
<конечноеЗначение> [Step
<приращение>] <блокОператоров> Next [<счетчик>] Несколько
пояснений к приведенному описанию:
Рассмотрим еще
одну разновидность цикла For. . .Next, часто использующуюся в VBA при обработке
объектов, составляющих массив или семейство однородных
объектов. В этой
разновидности цикла счетчик отсутствует, а тело цикла выполняется для каждого
элемента массива или семейства объектов. Вот синтаксис такого
цикла: For Each
<элемент> In <совокупность> <блокОператоров> Next
[<элемент>] где: <элемент>
— это переменная, используемая для ссылки на элементы семейства
объектов; <совокупность> — это имя массива или семейства. Приведем пример
использования подобного цикла. Следующая процедура предназначается для выдачи на
печать списка всех полей для всех таблиц текущей открытой базы
данных: Public Sub EnumerateAllFields() Dim MyBase As Database Dim tdf As TableDef, fid As Field Set MyBase = CurrentDb() For Each tdf In
MyBase.TableDefs Debug.Print "Таблица: " & tdf.Name For Each fid In
tdf.Fields Debug.Print " Поле:
" & fid.Name Next fid Next tdf Set MyBase = Nothing End
Sub Итак, в
операторах Dim мы объявили переменную MyBase как объект "база данных DАО",
переменные tdf и fid — как определение таблицы и поле таблицы, соответственно.
Оператор Set назначает переменной MyBase текущую открытую базу данных. Далее для
каждого определения таблицы выполняется вывод на печать названия таблицы, а
затем вложенный цикл такого же типа печатает названия всех ее
полей. Приведем еще
один пример использования подобного оператора цикла For Each. . .Next для
обработки всех элементов многомерного массива. Пусть у нас имеется трехмерный
числовой массив из 1000 элементов (размерами 10x10x10), который мы хотим
заполнить случайными вещественными числами в диапазоне от 0 до 1. Если бы мы
применяли обычные циклы For. . .Next со счетчиками, используя счетчики в
качестве индексов элементов массива, то для решения этой задачи потребовалось бы
написать три вложенных цикла For. . . Next: Dim tArray{9, 9, 9)
As Single Dim i%, j%,
k% Randomize For i=0 To
9 For j=0 To
9 For k=0 To
9 tArray(i, j, k) = Rnd() Next k Next j Next i На самом же деле
достаточно всего одного цикла, если вместо циклов со счетчиками воспользоваться
циклом For Each . . . Next: Dim tArray(9, 9, 9)
As Single Dim elem As
Variant Randomize For Each elem In
tArray elem = Rnd() Next Еще раз
порекомендуем использовать отступы при записи циклов, так же, как и при записи
операторов ветвления. Обычно
выполнение процедуры заканчивается после выполнения ее последнего оператора, а
выполнение цикла — после нескольких выполнений тела цикла, когда достигнуто
условие завершения его работы. Однако в некоторых случаях бывает нужно
прекратить выполнение процедуры или цикла досрочно, избежав выполнения лишних
операторов процедуры или лишних повторений цикла. Например, если при выполнении
процедуры произошла ошибка, которая делает продолжение ее работы бессмысленным,
можно выполнить команду немедленного выхода из процедуры. Другой пример: если
цикл For. . .Next используется для поиска нужного значения в массиве, то после
того, как нужный элемент массива найден, нет смысла продолжать дальнейший
перебор элементов массива. Досрочный выход из управляющей конструкции можно
осуществить с помощью одного из операторов Exit. Для досрочного выхода из циклов
Do. . .Loop используется оператор Exit Do, a для выхода из циклов For — оператор
Exit For. Для досрочного выхода из процедур и функций применяются операторы Exit
Sub и Exit Function соответственно. Следует, однако, отметить, что хотя
использование оператора Exit может быть вполне оправданным, необходимо избегать
излишнего употребления этого оператора, прибегая к нему только в крайних
случаях. Излишне частое употребление данного оператора затрудняет понимание
написанного текста программы и его отладку. Например, в
следующем цикле поиска For. . .Next используется оператор Exit For: ub = Ubound(dArray) fFound =
False For
i=LBound(dArray) To ub If dArray(i) = searchValue Then fFound = True Exit For End If
Next Однако такого применения оператора Exit вполне можно избежать. Вот пример подобного же цикла поиска, но без использования Exit: i = Lbound(dArray) ub = Ubound(dArray) fFound = False
Do If dArray(i) = searchValue Then fFound =
True i = i +
1 Loop Until (i >
ub) Or fFound На этом мы
заканчиваем краткое знакомство с основными понятиями языка VBA. Если читателю
требуется более подробное и строгое изложение синтаксиса языка, то лучше
обратиться к специальным книгам, посвященным этому языку. В других разделах
настоящей главы, а также в последующих главах мы покажем, как VBA используется
при разработке приложений, и познакомим с теми его особенностями, которые
специфичны именно для Access. Это касается в первую очередь объектов Access и
объектов данных. Объектные модели Microsoft Access
2002 Язык Visual
Basic for Applications является объектно-ориентированным языком
программирования. Стандартные объекты Visual Basic представляют собой основное
средство манипуляции с данными Microsoft Access и других приложений семейства
Microsoft Office. Знание технологии объектно-ориентированного программирования и
состава объектных моделей Visual Basic позволяет разрабатывать профессиональные
приложения, выполняющие всю необходимую обработку данных. Начнем с определения основных понятий, которые потребуются для понимания работы с объектами в языке VBA. Такими понятиями в данном случае будут:
Объект —
это абстракция, с которой мы оперируем в объектно-ориентированных г
языках программирования. Объект обладает собственными характерными
признаками, отличающими
его от других объектов, и имеет свое поведение. Примерами объектов Access
являются уже известные вам таблицы, формы, отчеты, запросы. Класс
представляет собой описание совокупности однотипных объектов. Класс можно
сравнить с типом данных, где переменной такого специфического типа является
объект. В этом случае говорят, что объект представляет собой экземпляр
определенного класса. Каждый объект
имеет свойства и методы, которые различны у разных классов объектов, но
применяются они одинаково, в чем вы скоро убедитесь на примерах использования
объектов в процедурах VBA. Свойством
называют отдельную характеристику объекта или класса. Например, знакомые уже
вам свойства формы являются свойствами объекта Form. Свойство .объекта может
принимать определенное значение. Например, свойство Вывод на экран
(Visible) может принимать значение True или False, в зависимости от чего
форма будет появляться или исчезать с экрана. Метод
представляет собой процедуру (или функцию) объекта или класса. Совокупность
методов объекта определяет его "поведение". Например, объект Form имеет метод
Refresh, вызов которого позволяет обновить данные в форме Access. Объект может
реагировать на определенные события, происходящие в процессе работы
приложения и влияющие на объект. Совокупность событий, на которые объект
способен реагировать, определяется создателем класса, экземпляром которого
является данный объект. Например, набор событий, которые определены для формы
Access, мы видим на вкладке События (Event) диалогового окна Свойства
(Properties). Реакцией объекта на произошедшее событие может быть выполнение
объектом некоторой специальной процедуры, которая называется процедурой
обработки события. Любому событию объекта может быть назначена некоторая
процедура его обработки. Упорядоченный
набор однотипных объектов — экземпляров одного класса называется семейством.
Семейство тоже является объектом. Одним из методов этого объекта является
процедура, возвращающая ссылку на конкретный объект в семействе. Одним из
свойств семейства является число объектов, хранящихся в нем. Например,
совокупность элементов управления в форме образует семейство
Controls. Объекты и
семейства сгруппированы в виде иерархических структур, которые называются
объектными моделями. В VBA определены специальные объектные модели для
каждого компонента семейства Microsoft Office и объектные модели, общие для всех
компонентов Microsoft Office. Объектные модели VBA можно изучать, используя
справочную систему и окно просмотра объектов. Окно просмотра объектов
представляет собой специальное средство редактора Visual Basic, позволяющее
просматривать содержимое библиотек объектов и производить поиск справочной
информации. (Описание окна просмотра объектов можно найти в данной главе, в
разд. "Среда программирования Access 2002".) Объектные модели Microsoft Office 2002 Управление
приложениями семейства Microsoft Office 2002 осуществляется интерактивно — с
помощью интерфейса пользователя или программно — с помощью объектных моделей.
Каждый из компонентов Microsoft Office предоставляет свои объектные модели в виде одноименной
библиотеки объектов (файл с расширением olb), которая может быть использована в
других приложениях. Microsoft Access 2002, как компонент Microsoft Office, имеет
такую библиотеку — Microsoft Access 10.0 Object Library. Доступ и управление
данными в Microsoft Access могут осуществляться с помощью объектных моделей,
реализованных в нескольких библиотеках:
|