26.12.2014 Views

Управление базами данных Access на VBA - eDrive

Управление базами данных Access на VBA - eDrive

Управление базами данных Access на VBA - eDrive

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

В. М. Водовозов<br />

<strong>Управление</strong> <strong>базами</strong> <strong>данных</strong><br />

<strong>Access</strong> <strong>на</strong> <strong>VBA</strong><br />

Санкт-Петербург<br />

2003


УДК 681.3.016<br />

В.М.Водовозов. <strong>Управление</strong> <strong>базами</strong> <strong>данных</strong> <strong>Access</strong> <strong>на</strong> <strong>VBA</strong>. 32 с.<br />

Даны основные сведения об использовании Visual Basic for<br />

Applications для создания модулей <strong>Access</strong>. Для всех, кто владеет основами<br />

Microsoft <strong>Access</strong>.<br />

© В.М.Водовозов, 2003.


Оглавление<br />

Модели объектов <strong>Access</strong>.................................................................................3<br />

Процедурное и структурное программирование в DAO .............................5<br />

Процедурное и структурное программирование в ADO ...........................13<br />

Визуальное программирование в <strong>Access</strong>.....................................................21<br />

Меню...............................................................................................................31<br />

Панели инструментов....................................................................................32<br />

Началь<strong>на</strong>я установка интерфейса ................................................................34<br />

Модели объектов <strong>Access</strong><br />

<strong>Access</strong> представлен двумя уровнями компонентов: ядром базы <strong>данных</strong><br />

Jet и системой управления базой <strong>данных</strong> <strong>Access</strong>. На уровне ядра <strong>на</strong>ходятся<br />

данные, то есть таблицы и запросы, а также файлы, хранящие компоненты<br />

системы управления. Для организации <strong>данных</strong> используется индекснопоследовательный<br />

метод (ISAM), в соответствии с которым каждая запись<br />

имеет переменную длину и хранится <strong>на</strong> странице объемом до двух килобайт.<br />

Выборка <strong>данных</strong> поддерживается механизмом запросов SQL и программным<br />

доступом <strong>на</strong> <strong>VBA</strong>. Система управления <strong>Access</strong> обслуживает интерфейс<br />

пользователя (формы, отчеты, макросы, меню, панели, ок<strong>на</strong> диалога) и<br />

процедуры <strong>VBA</strong>.<br />

Первый уровень поддерживаются двумя моделями объектов. Первая из<br />

них базируется <strong>на</strong> библиотеках классов DAO (Data <strong>Access</strong> Objects), вторая —<br />

<strong>на</strong> библиотеках ADO (ActiveX Data Objects — ADODB, ActiveX Data Objects<br />

Extensions for DDL and Sequrity — ADOX, Microsoft Jet and Replication<br />

Objects — JRQ). ADODB обеспечивает приложению доступ к источнику<br />

<strong>данных</strong> с возможностью отбора и изменения <strong>данных</strong>. ADOX позволяет<br />

программно изменять структуру объектов источника <strong>данных</strong> и систему<br />

защиты баз <strong>данных</strong>. JRQ служит для создания, модификации и<br />

синхронизации реплик баз <strong>данных</strong> <strong>Access</strong>.<br />

Второй уровень строится <strong>на</strong> библиотеке <strong>Access</strong>.<br />

Библиотека классов DAO ориентирова<strong>на</strong> <strong>на</strong> работу с данными. Базовым<br />

классом DAO является DBEngine, описывающий семейства Errors (Ошибки)<br />

и Workspaces (Рабочие области). Каждая рабочая область Workspace<br />

характеризуется классами Databases (Базы <strong>данных</strong>), Groups (Группы), Users<br />

(Пользователи). Наиболее часто используется семейство Recordset<br />

(Результирующие <strong>на</strong>боры записей) класса Database. Каждое множество<br />

Recordset основывается <strong>на</strong> записях таблицы или <strong>на</strong> описании запроса и<br />

позволяет <strong>на</strong>ходить, добавлять, изменять или удалять записи. Структуры<br />

таблиц базы <strong>данных</strong> хранятся в семействе класса TableDefs, в частности, в<br />

объектах его классов Fields (Поля), Indexes (Индексы). В семействе класса


4<br />

Relations (Связи) размещаются схемы <strong>данных</strong> таблиц. Структура запросов<br />

базы <strong>данных</strong> описывается семейством класса QueryDefs (Запросы) с<br />

объектами классов Fields (Поля), Parameters (Параметры).<br />

На работу с данными рассчита<strong>на</strong> и модель ADO. Во главе этой модели<br />

стоит объект Connection (Соединение). Он описывает среду, в которой<br />

выполняется обмен данными. Источник <strong>данных</strong> управляется производным от<br />

Connection объектом Command (Команда), который командами SQL<br />

добавляет, удаляет, обновляет и считывает данные. Его семейство Parameters<br />

(Параметры) представляет переменные компоненты объекта Command.<br />

Другой производный от Connection объект — Recordset — <strong>на</strong>капливает<br />

считанные из источника данные. Его семейство Fields представляет поля<br />

таблиц Recordset. Поля характеризуются семействами свойств Properties.<br />

Встроенные свойства являются частью объекта ADO и всегда доступны, а<br />

ди<strong>на</strong>мические свойства существуют только в момент работы источника<br />

<strong>данных</strong>.<br />

Библиотеку классов <strong>Access</strong> возглавляет класс Application<br />

(Приложение), описывающий семейства Forms, Reports, Modules, References,<br />

Data<strong>Access</strong>Pages, Controls и такие объекты как Screen, DoCmd, Module,<br />

Assistant, CommandBar…<br />

В литературе часто используются сокращения:<br />

Приз<strong>на</strong>к Тип Объект Приз<strong>на</strong>к Тип Объект<br />

db Database База <strong>данных</strong> rpt Report Отчет<br />

tdf TableDef Таблица ctl Control Элемент<br />

qdf QueryDef Запрос txt TextBox Поле формы<br />

rst Recordset Набор записей cbo ComboBox Поле со списком<br />

fld Field Поле cmd Command Кнопка<br />

Button<br />

idx Index Индекс con Connection Связь<br />

frm Form Форма cmd Command Команда меню<br />

Обращение к чле<strong>на</strong>м библиотек классов DAO и ADO и все обращения в<br />

запросах SQL выполняется по схеме:<br />

имяКласса.имяОбъекта.Член<br />

Име<strong>на</strong> длиной более одного слова заключаются в прямоугольные<br />

скобки. При ссылке <strong>на</strong> объект в активном окне базы <strong>данных</strong> или контейнера<br />

(объекта, содержащего адресуемый объект) имя класса иногда можно<br />

опускать. Для упрощения обращений к объектам используется оператор Set,<br />

ставящий в соответствие описываемому объекту объектную переменную.


5<br />

Процедурное и структурное программирование в DAO<br />

В общем случае доступ к данным библиотек DAO организуется в три<br />

этапа. С<strong>на</strong>чала создается объект методом Create… его родителя. Затем<br />

уста<strong>на</strong>вливаются его свойства, которые после сохранения объекта в базе<br />

<strong>данных</strong> останутся доступными только для чтения. В ряде случаев, кроме<br />

свойств, сразу же задаются и объекты-потомки, <strong>на</strong>пример, поля таблиц. В<br />

заключение объект добавляется в состав семейства методом Append этого<br />

семейства и сохраняется в памяти. Отдельные классы объектов создаются по<br />

упрощенной схеме.<br />

Сеанс доступа к данным модели DAO описывает класс Workspace. Все<br />

действия в рамках сеанса определены правилами доступа пользователя, а их<br />

последовательность — транзакция — рассматривается как одно целое. В<br />

незащищенных базах <strong>данных</strong> открывается сеанс по умолчанию под именем<br />

Default Workspace для пользователя admin без пароля. При создании нового<br />

сеанса Workspace<br />

DBEngine!CreateWorkspace _<br />

(имяРабочейОбласти, Пользователь, Пароль [, Тип])<br />

его не добавляют в семейство ввиду временного характера его<br />

существования.<br />

Метод CreateDatabase используют для создания новых баз <strong>данных</strong>:<br />

[рабочаяОбласть].CreateDatabase (имяБазыДанных, _<br />

Язык, [Параметры] )<br />

Здесь ранее создан<strong>на</strong>я рабочаяОбласть служит ссылкой <strong>на</strong> объект<br />

Workspace, имяБазыДанных длиной до 255 символов представляет короткий<br />

или полный путь к файлу .MDB, Язык задается з<strong>на</strong>чением констант<br />

dbLangGeneral, dbLangCirillic, определяя порядок сортировки <strong>данных</strong>, а<br />

необязательные Параметры задают формат ядра Jet и необходимость<br />

шифрования. Базы <strong>данных</strong> автоматически добавляются в соответствующие<br />

семейства и сохраняются.<br />

Для открытия базы <strong>данных</strong> используется метод OpenDatabase:<br />

[базаДанных.] [рабочаяОбласть.]OpenDatabase (имяБазыДанных _<br />

[, Монопольность [, толькоЧтение[, Источник]]] )<br />

Если база <strong>данных</strong> уже открыта, к ней удобно обращаться через функцию<br />

CurrentDb:<br />

• CurrentDB!имяТаблицы!имяПоля.имяСвойства


6<br />

• CurrentDB!QueryDefs!имяЗапроса<br />

• CurrentDB!QueryDefs («имяЗапроса»)<br />

• CurrentDB!QueryDefs (индекс)<br />

• CurrentDB!QueryDefs (ссылка)<br />

Результирующие множества записей — объекты классов TableDef и<br />

QueryDef — создаются методами CreateTableDef, CreateQueryDef:<br />

• [рабочаяОбласть.]базаДанных.CreateTableDef («имяТаблицы»)<br />

• [рабочаяОбласть.]базаДанных.CreateQueryDef ([запрос, SQL])<br />

Если при вызове метода CreateQueryDef аргументы не заданы, можно<br />

присвоить новому объекту з<strong>на</strong>чения свойств Name и SQLtext позднее,<br />

посредством оператора присваивания.<br />

Объекты классов TableDef и QueryDef открываются методом<br />

OpenRecordset и закрываются с удалением из семейства Databases методом<br />

Close объекта Database:<br />

• базаДанных.OpenRecordset (Источник [,Тип, Параметры] )<br />

• объект.OpenRecordset (Источник [,Тип, Параметры] )<br />

• базаДанных.Close<br />

• объект.Close<br />

В отличие от режима работы через интерфейс пользователя, процедуры <strong>VBA</strong><br />

дают возможность одновременно открывать несколько баз <strong>данных</strong>, хотя <strong>на</strong><br />

экране отображается только од<strong>на</strong> из них. Свойство Name позволяет<br />

проверить, открылась ли база <strong>данных</strong>: полный путь к открытой базе<br />

возвращает выражение объект.Name.<br />

Поля таблиц в<strong>на</strong>чале создаются, затем добавляются в семейства, после<br />

чего обновляется окно базы <strong>данных</strong>:<br />

Set объектПоле = объектТаблица.CreateField (имяПоля, Тип, [Размер])<br />

объектТаблица.Fields.Append объектПоле<br />

базаДанных.TableDefs.Append объектТаблица<br />

RefreshDatabaseWindow<br />

Доступ к полям реализуется через объекты класса Fields:<br />

• имяТаблицыИлиЗапроса.Fields!имяПоля<br />

• имяТаблицыИлиЗапроса. имяПоля<br />

• имяТаблицыИлиЗапроса!Fields!имяПоля<br />

• имяТаблицыИлиЗапроса! имяПоля


7<br />

• Parent!имяПоляГлавнойФормы<br />

Ни TableDef, ни QueryDef не содержат <strong>данных</strong>. Для доступа к данным<br />

нужны <strong>на</strong>боры записей — объекты RecordSet. В модели DAO присутствуют<br />

четыре типа таких объектов. Тип Table представляет <strong>на</strong>бор записей одной<br />

таблицы открытого файла базы <strong>данных</strong>. Он не обрабатывает связанные<br />

таблицы и таблицы ODBC и обслуживает только рабочие области Jet. Тип<br />

Dynaset представляет ди<strong>на</strong>мический <strong>на</strong>бор записей таблицы открытой базы<br />

<strong>данных</strong>, связанной таблицы, результата выполнения запроса или оператора<br />

SQL SELECT. Он состоит из ссылок, поэтому обрабатывается медленнее,<br />

чем Table и иногда не обновляется, но охватывает более широкую область<br />

<strong>данных</strong>. Тип Snapshot представляет статическую копию таблицы, запроса или<br />

оператора SQL SELECT, удобную для выборки <strong>данных</strong> и создания отчетов.<br />

Forward-Only представляет а<strong>на</strong>логичную копию, пред<strong>на</strong>з<strong>на</strong>ченную для<br />

единовременного просмотра <strong>данных</strong>. Синтаксис:<br />

базаДанных.OpenRecordSet (Источник [,Тип, Параметры, Блокировка])<br />

Здесь Источник — это строка с именем таблицы, запроса или текстом SQL,<br />

далее следует тип объекта RecordSet, по умолчанию Table для таблиц и<br />

Dynaset для запросов и связанных таблиц. Любой объект RecordSet<br />

существует только в рамках своей процедуры, а затем уничтожается. Его<br />

можно закрыть раньше методом Close.<br />

Примеры<br />

Sub РабочаяОбласть ()<br />

Set область = DBEngine.Workspaces (0)<br />

Set новаяБазаДанных = _<br />

область.CreateDatabase ("Школьники.mdb", dbLangGeneral)<br />

Set другаяБазаДанных = _<br />

область.OpenDatabase ("Транспорт")<br />

MsgBox другаяБазаДанных.Name & Chr (13) & _<br />

новаяБазаДанных.Name & Chr (13) & CurrentDb.Name<br />

End Sub<br />

Sub БазыДанных ()<br />

Set текущаяБазаДанных = CurrentDb<br />

Set новаяБазаДанных = CreateDatabase ("Студенты.mdb", dbLangCyrillic)<br />

Set другаяБазаДанных = OpenDatabase ("Пользователи.mdb")<br />

MsgBox другаяБазаДанных.Name & Chr (13) & _<br />

новаяБазаДанных.Name & Chr (13) & текущаяБазаДанных.Name<br />

End Sub<br />

Sub НаборыЗаписейDAO ()<br />

Set tdf1 = CurrentDb.OpenRecordset ("Сотрудники", dbOpenDynaset)<br />

Set tdf2 = CurrentDb.OpenRecordset ("Категории")


8<br />

Set tdf3 = CurrentDb.OpenRecordset ("SELECT * FROM Поставщики")<br />

Set tdf4 = CurrentDb!Поставщики.OpenRecordset<br />

Set tdf5 = CurrentDb.QueryDefs (“Продажи”).OpenRecordset<br />

tdf1.Close<br />

End Sub<br />

Sub <strong>Управление</strong>Таблицей ()<br />

Set tdf = CurrentDb.OpenRecordset ("Отделы")<br />

MsgBox "Таблица открыта"<br />

tdf.Close<br />

MsgBox "Таблица закрыта"<br />

End Sub<br />

Sub СозданиеТаблицы ()<br />

Set область = DBEngine.Workspaces (0)<br />

Set база = область.OpenDatabase (“C:\Учащиеся.mdb”)<br />

Set таблица = база.CreateTableDef ("НоваяТаблица")<br />

таблица.Fields.Append таблица.CreateField (“Кто”, dbText)<br />

таблица.Fields.Append таблица.CreateField (“Когда”, dbDate)<br />

база.TableDefs.Append таблица<br />

база.TableDefs.Refresh<br />

Set таблица = Nothing<br />

Set база = Nothing<br />

End Sub<br />

Sub УдалениеТаблицы ()<br />

CurrentDb.TableDefs.Delete “НоваяТаблица”<br />

CurrentDb.TableDefs.Refresh<br />

RefreshDatabaseWindow<br />

End Sub<br />

Sub ДоступКПолям ()<br />

MsgBox CurrentDb!Таблица1.Fields (1).Name & Space (2) _<br />

& CurrentDb!Таблица1.Fields (2).Name & Chr (13) & _<br />

"Всего полей: " & CurrentDb!Сотрудники.Fields.Count<br />

End Sub<br />

Sub Запрос ()<br />

перемен<strong>на</strong>я = CurrentDB.CreateQueryDef _<br />

(“зСотр”, “SELECT * FROM Сотрудники ORDER BY Сотрудники.ФИО”)<br />

RefreshDatabaseWindow<br />

End Sub<br />

При создании объекта RecordSet строки <strong>данных</strong> помещаются в буфер и<br />

не выводятся <strong>на</strong> экран, а указатель позиционирует <strong>на</strong> текущей записи. При<br />

открытии <strong>на</strong>бора записей активной становится первая запись. Для<br />

перемещения к другим записям используются методы MoveFirst, MoveNext,<br />

MovePrevious, MoveLast. Методом BookMark можно определять закладки и<br />

возвращаться впоследствии к запомненным в них записям:<br />

объектЗакладка = объектНабор.BookMark


9<br />

Метод<br />

…<br />

объектНабор.BookMark = объектЗакладка<br />

Move числоСтрок [,Закладка]<br />

смещает указатель <strong>на</strong> требуемое число записей вперед или <strong>на</strong>зад. Свойства<br />

BOF и EOF объекта Recordset фиксируют выход за пределы <strong>на</strong>бора записей.<br />

Для поиска определенной записи в <strong>на</strong>борах типа Table используется<br />

метод Seek, а в <strong>на</strong>борах других типов — методы FindFirst, FindNext,<br />

FindPrevious, FindLast. Найден<strong>на</strong>я запись становится текущей, а свойство<br />

NoMatch уста<strong>на</strong>вливается в False. При отсутствии искомой записи NoMatch =<br />

True:<br />

• объект.Seek «оператор», списокКлючей<br />

• объект.Find… «критерий»<br />

Здесь используются операторы >, =,


10<br />

Удаляемая запись помещается в буфер удаления и остается текущей.<br />

Удаление выполняется без предупреждения и отмены.<br />

Уникальный объект DoCmd реализует связь между<br />

макропрограммированием и программированием <strong>на</strong> <strong>VBA</strong>, дублируя операции<br />

интерфейса пользователя <strong>Access</strong>. Методы DoCmd не возвращают з<strong>на</strong>чений. В<br />

их аргументах активно используются константы <strong>Access</strong>, такие как acTable,<br />

acQuery, acForm, acReport, True, False. Име<strong>на</strong> объектов здесь не заключаются<br />

в прямоугольные скобки, а при необходимости помещаются в двойные<br />

кавычки. В частности, для выполнения запросов SQL вызывается метод<br />

RunSQL объекта DoCmd. В программах <strong>VBA</strong> допускается использование<br />

выражений SQL длиной до 32768 символов.<br />

Другой метод — Clone — создает копии <strong>на</strong>боров записей. При<br />

копировании организуется независимый указатель текущей записи, а<br />

закладки копии совпадают с закладками ориги<strong>на</strong>ла. Но копия не <strong>на</strong>следует<br />

свойств Index, Filter, Sort.<br />

Связь полей таблиц и запросов описывается методом Relation. Он<br />

используется для создания новых связей (CreateRelation), для их изменения и<br />

просмотра. При создании связи указываются соответствующие поля в<br />

первичной и внешней таблицах (запросах). В первой таблице эти поля<br />

образуют первичный ключ, одноз<strong>на</strong>чно определяющий запись, а во второй<br />

таблице — внешний ключ. Каждое поле первичного ключа следует добавить<br />

в семейство Fields связи с указанием внешнего ключа в свойстве<br />

ForeignName:<br />

Set объектСвязи = базаДанных.CreateRelation<br />

([«Имя», Таблица, внешняяТаблица, Атрибуты])<br />

объектСвязи.Table = «Таблица»<br />

объектСвязи.ForeignTable = «внешняяТаблица»<br />

Set объектПоле = объектСвязи.CreateField(«Поле»)<br />

объектПоле.ForeignName = «Поле»<br />

объектСвязи.Fields Append объектПоле<br />

базаДанных.Relations Append объектСвязи<br />

При этом <strong>Access</strong> уста<strong>на</strong>вливает параметр ссылочной целостности, но не<br />

уста<strong>на</strong>вливает каскадное обновление и удаление записей.<br />

Примеры<br />

Sub ПоискDAO ()<br />

Set tdf1 = CurrentDb.OpenRecordset ("Сотрудники")<br />

tdf .Index = "PrimaryKey"<br />

tdf .Seek "=", "Иванов"<br />

Set tdf2 = CurrentDb.OpenRecordset ("Командировки", dbOpenSnapshot)


11<br />

tdf2.FindFirst "Кто = 'Алексеев'"<br />

End Sub<br />

Sub ЗаписиDAO ()<br />

Set базаДанных = CurrentDb<br />

строкаSQL = "SELECT * FROM Таблица1 WHERE Фирма LIKE 'I*'"<br />

Set результатЗапроса = базаДанных.OpenRecordset (строкаSQL)<br />

результатЗапроса.MoveFirst<br />

MsgBox результатЗапроса.Fields (0) & " - " & результатЗапроса.Fields (2)<br />

где = "Фирма = 'Intel'"<br />

результатЗапроса.FindFirst где<br />

MsgBox результатЗапроса.Fields (0) & " - " & результатЗапроса.Fields (2)<br />

результатЗапроса.FindNext где<br />

MsgBox результатЗапроса.Fields (0) & " - " & результатЗапроса.Fields (2)<br />

результатЗапроса.MoveLast<br />

MsgBox результатЗапроса.RecordCount<br />

End Sub<br />

Sub ОбновлениеЗаписей ()<br />

Set rst = CurrentDb.OpenRecordset ("Таблица1")<br />

где = "Фирма = 'Intel'"<br />

DoCmd.RunSQL _<br />

"UPDATE Таблица1 SET Це<strong>на</strong> = 5 WHERE NТовара=2"<br />

DoCmd.RunSQL _<br />

"UPDATE Таблица1 SET Фирма = 'LG' WHERE " & где<br />

DoCmd.RunSQL _<br />

"UPDATE Таблица1 SET Фирма = 'Zilog' WHERE " & _<br />

"Фирма = 'LG'"<br />

rst.Close<br />

Set rst = Nothing<br />

End Sub<br />

Sub А<strong>на</strong>лизЗаписей ()<br />

Set db = CurrentDb<br />

Set rst = db.OpenRecordset ("Таблица1", dbOpenDynaset)<br />

где = "Фирма = 'Intel'"<br />

rst.MoveFirst<br />

rst.FindFirst где<br />

If rst.NoMatch = False Then MsgBox "Фирма есть в этой таблице"<br />

rst.FindNext где<br />

If rst.NoMatch Then MsgBox "Фирма только од<strong>на</strong>"<br />

rst.Close<br />

db.Close<br />

Set rst = Nothing<br />

Set db = Nothing<br />

End Sub<br />

Sub СписокБазыДанных ()<br />

Set текущаяБазаДанных = CurrentDb<br />

Set рабочаяОбласть = DBEngine.Workspaces(0)<br />

Set новаяБазаДанных = рабочаяОбласть.CreateDatabase _<br />

("Студенты.mdb", dbLangGeneral)


12<br />

Set другаяБазаДанных = рабочаяОбласть.OpenDatabase _<br />

("ФирмаГодПрезидент")<br />

For Each базаДанных In рабочаяОбласть.Databases<br />

список = список & Chr (13) & базаДанных.Name<br />

Next базаДанных<br />

MsgBox список<br />

End Sub<br />

Sub СписокПолей ()<br />

Set db = CurrentDb<br />

Set tdf = db!Таблица1<br />

For Each fld In tdf.Fields<br />

строка = строка & Chr (13) & fld.Name<br />

Next fld<br />

MsgBox строка<br />

End Sub<br />

Sub Заме<strong>на</strong>Данных ()<br />

Set объект = CurrentDb.OpenRecordset ("Товары", dbOpenDynaset)<br />

критерий = "NТовара = 1"<br />

объект.FindFirst критерий<br />

Do Until объект.NoMatch<br />

With объект<br />

.Edit<br />

.NТовара = 333<br />

.Update<br />

.FindNext критерий<br />

End With<br />

Loop<br />

объект.Close<br />

Set объект = Nothing<br />

End Sub<br />

Sub ЧтениеДанных ()<br />

‘ В <strong>Access</strong> для загрузки в массив строк объекта Recordset<br />

‘ используется метод GetRows<br />

Set объект = CurrentDb.OpenRecordset("Товары")<br />

массив = объект.GetRows (объект.RecordCount)<br />

For Each элемент In массив<br />

строка = строка & элемент & chr (13)<br />

Next<br />

MsgBox строка<br />

End Sub<br />

Sub ПравкаТаблицDAO ()<br />

Set таблица = CurrentDB.OpenRecordset ("Таблица1")<br />

таблица.MoveFirst<br />

таблица.Edit<br />

таблица.Fields (Фирма) = "SCAN"<br />

таблица.Fields (Год) = 2005<br />

строкаSQL = "UPDATE Таблица1 SET NТовара = 22 " _


13<br />

& "WHERE NТовара = 2 "<br />

CurrentDb.Execute строкаSQL<br />

таблица.AddNew<br />

таблица.Fields (ФИО) = “Новый”<br />

таблица.Update<br />

таблица.BookMark = таблица.LastModified<br />

таблица.Move 5<br />

таблица.Delete<br />

таблица.moveNext<br />

End Sub<br />

Процедурное и структурное программирование в ADO<br />

Синтаксис обращения к объектам ADO:<br />

ADODB.имяОбъекта<br />

Для доступа к данным в этой модели используются объекты Connection,<br />

несущие сведения об источнике <strong>данных</strong> и его расположении. Для работы с<br />

ним открывается множество Recorddet или Command и задается строка<br />

подключения ConnectionString. З<strong>на</strong>чения каждого свойства такого объекта<br />

можно задавать как аргумент метода Open или отдельно, через свойство<br />

Properties. Connection открывает сеанс обме<strong>на</strong> данными через провайдера<br />

OLEDB. Command служит для выполнения запросов. Recordset представляет<br />

<strong>на</strong>бор записей, а Fields — семейство его полей. Отдельные параметры SQLзапросов<br />

и хранимых процедур образуют семейство Parameter. Ошибки<br />

сеанса связи фиксируются объектами семейства Errors. Как и в DAO,<br />

свойства — объекты Properties — делятся <strong>на</strong> встроенные и ди<strong>на</strong>мические.<br />

Можно с<strong>на</strong>чала задавать свойства, а потом создавать объект, используя его<br />

метод или метод другого объекта. Или <strong>на</strong>оборот: в<strong>на</strong>чале создать объект, а<br />

затем установить з<strong>на</strong>чения его свойств.<br />

Свойства и методы классов модели ADODB приведены в таблице.<br />

Название Тип Определение<br />

Класс Connection<br />

Initial Catalog Свойство Папка по умолчанию<br />

Data Source Свойство Источник <strong>данных</strong>: таблица, запрос…<br />

User ID Свойство Сетевое имя пользователя<br />

Integrated Sequrity Свойство Интегрироаван<strong>на</strong>я защита<br />

Prompt Свойство Ввод пароля<br />

Persist Sequrity<br />

Info<br />

Свойство Пароль в строке подключения<br />

CursorLocation Свойство Клиентские курсоры<br />

ConnectionString Свойство Строка подключения со списком свойств


14<br />

Название Тип Определение<br />

State Свойство Состояние объекта Connection<br />

Open Метод Создает новый объект Connection<br />

Execute Метод Выполняет команду<br />

Класс Recordset<br />

AbsolutePosition Свойство Уста<strong>на</strong>вливает указатель <strong>на</strong> текущей записи<br />

BOF, EOF Свойство Определяет <strong>на</strong>чало и конец <strong>на</strong>бора записей<br />

Bookmark Свойство Сохраняет позицию указателя в <strong>на</strong>боре<br />

Connection Свойство Объект<strong>на</strong>я перемен<strong>на</strong>я соединения<br />

RecordCount Свойство Число записей в <strong>на</strong>боре<br />

Close Метод Закрывает <strong>на</strong>бор записей<br />

Delete Метод Удаляет текущую запись из <strong>на</strong>бора<br />

GetRows Метод Копирует записи в двухмерный массив<br />

Move Метод Смещает указатель <strong>на</strong> заданную величину<br />

MoveFirst, Move-<br />

Переходит к первой, последней, следующей<br />

Last, MoveNext, Метод<br />

или предыдущей записи, делая ее текущей<br />

MovePrevious<br />

OpenRecordset Метод Создает новый <strong>на</strong>бор записей<br />

Requery Метод Обновляет <strong>на</strong>бор, переходя в ее <strong>на</strong>чало<br />

Класс Command<br />

ActiveConnection Свойство Уста<strong>на</strong>вливает подключение или его строку<br />

CommandText Свойство Источник: SQL-инструкция, таблица<br />

CommandType Свойство Тип свойства CommandText<br />

CommandTimeout Свойство Время ожидания выполнения запроса, с<br />

Prepared Свойство Предваритель<strong>на</strong>я готовность CommandText<br />

State Свойство Состояние объекта Command<br />

Cancel Метод Прекращает выполнение запроса<br />

CreateParameter Метод Создает параметр запроса<br />

Execute Метод Выполняет запрос объекта Command<br />

Объекты Recordset создают тремя методами: Open класса Recordset,<br />

Exequte класса Command или Exequte класса Connection. Синтаксис метода<br />

Open:<br />

rst.Open Source, Connection, CursorType, lockType, Options<br />

где Source — это имя таблицы или запроса, инструкция SQL, ссылка <strong>на</strong><br />

объект Command или имя файла, Connection — ссылка <strong>на</strong> объект<br />

подключения, cursorType — тип доступа: adOpenDynamic — отображает все<br />

изменения, вставки и удаления, вносимые другими пользователями;<br />

adOpenKeyset — показывает только изменения; adOpenStatic — сохраняет<br />

исходный <strong>на</strong>бор; adOpenForwardOnly — то же, при одностороннем движении<br />

курсора; LockType — тип блокировки: adLockReadOnly — только для чтения,


15<br />

adLockPessimistic — пессимистическая блокировка, adLockOptimistic —<br />

оптимистическая блокировка, adLockBatchOptimistic — с кэшированием<br />

изменений в <strong>на</strong>боре; Options — характеристика Source: adCmdText —<br />

инструкция SQL, adCmdTable — SQL-запрос ко всем записям таблицы,<br />

adCmdTableDirect — таблица или запрос, adCmdUnknown — без указания<br />

параметра, adCmdFile — файл с <strong>на</strong>бором записей.<br />

Объект Command служит для выполнения запросов. В качестве<br />

источника <strong>данных</strong> запроса может задаваться таблица или SQL-инструкция,<br />

серверное представление или хранимая процедура. Его свойство<br />

CommandType при этом принимает одно из з<strong>на</strong>чений: adCmdUnknown —<br />

неизвестный, по умолчанию, adCmdText — запрос или хранимая процедура,<br />

adCmdTable — таблица для запроса, adCmdTableDirect — непосредственно<br />

открываемая таблица, adCmdStoredProc — хранимая процедура <strong>на</strong> сервере,<br />

adCmdFile — файл с <strong>на</strong>бором записей.<br />

Примеры<br />

Sub ТекущееСоединениеADO ()<br />

Dim cnn As ADODB.Connection<br />

Set cnn = CurrentProject.Connection<br />

MsgBox cnn.ConnectionString<br />

If cnn.State = adStateClosed Then<br />

MsgBox "Нет подключения"<br />

Else<br />

MsgBox "Подключение есть"<br />

End If<br />

Set cnn = Nothing<br />

End Sub<br />

Sub Соединение1ADO ()<br />

Dim cnn As ADODB.Connection<br />

Set cnn = New ADODB.Connection<br />

cnn.Open _<br />

"Provider=SQLOLEDB; Data Source=srv; Initial Catalog=pubs;" & _<br />

"DataBase=базаДанных; User Id=sa; Password=;"<br />

MsgBox cnn.ConnectionString<br />

If cnn.State = adStateClosed Then<br />

MsgBox "Нет подключения"<br />

Else<br />

MsgBox "Подключение есть"<br />

End If<br />

cnn.Close<br />

End Sub<br />

Sub Соединение2ADO ()<br />

Dim cnn As ADODB.Connection<br />

Set cnn = New ADODB.Connection<br />

cnn.Provider = "SQLOLEDB"<br />

cnn.Properties ("DataSource") = "Источник"


16<br />

cnn.Properties ("DataBase") = "базаДанных"<br />

cnn.Properties ("UserId") = "Пользователь"<br />

cnn.Properties ("Password") = "Пароль"<br />

cnn.Open<br />

MsgBox cnn.ConnectionString<br />

If cnn.State = adStateClosed Then<br />

MsgBox "Нет подключения"<br />

Else<br />

MsgBox "Подключение есть"<br />

End If<br />

cnn.Close<br />

End Sub<br />

Sub ДоступКПолямADO ()<br />

Dim rst As New ADODB.Recordset<br />

rst.Open "Сотрудники", CurrentProject.Connection<br />

For i = 0 To rst.Fields.Count - 1<br />

temp = temp & rst.Fields(i).Name & vbCr<br />

Next<br />

MsgBox "Всего полей: " & Str(rst.Fields.Count) & vbCr & temp<br />

End Sub<br />

Sub СвойстваADO ()<br />

Dim cnn As New ADODB.Connection, rst As New ADODB.Recordset<br />

cnn.Provider = "Microsoft.Jet.OLEDB.4.0"<br />

cnn.Properties ("Data Source") = "D:\ Кадры.mdb"<br />

cnn.Open<br />

rst.CursorType = adOpenStatic<br />

rst.Open “Сотрудники”, cnn<br />

' вот как можно уз<strong>на</strong>ть все свойства класса<br />

For i = 0 To cnn.Properties.Count - 1<br />

Debug.Print cnn.Properties (i).Name<br />

Next<br />

End Sub<br />

Public cnnXLS As New ADODB.Connection, _<br />

cnnMDB As New ADODB.Connection, _<br />

cnnDBF As New ADODB.Connection<br />

Public rstXLS As New ADODB.Recordset, _<br />

rstMDB As New ADODB.Recordset, _<br />

rstDBF As New ADODB.Recordset<br />

Sub Соединения ()<br />

Отключение<br />

cnnXLS.Open "DBQ=D:\ Сотрудники.xls;Driver={Microsoft Excel Driver (*.xls)}"<br />

RSTOpen "Сотрудники", cnnXLS, rstXLS<br />

cnnDBF.Open "DBQ=D:\;Driver={Microsoft dBase Driver (*.dbf)}"<br />

RSTOpen "T", cnnDBF, rstDBF


17<br />

cnnMDB.Open "DBQ=D:\ Кадры.mdb;Driver={Microsoft <strong>Access</strong> Driver (*.mdb)}"<br />

RSTOpen "Сотрудники", cnnMDB, rstMDB<br />

End Sub<br />

Sub RSTOpen (tbl As String, _<br />

cnn As ADODB.Connection, rst As ADODB.Recordset)<br />

MsgBox tbl & " connection: " & cnn.ConnectionString<br />

If cnn.State = adStateClosed Then<br />

MsgBox "Нет подключения к " & tbl<br />

Else<br />

rst.CursorType = adOpenStatic<br />

rst.Open tbl, cnn<br />

End If<br />

End Sub<br />

Sub Отключение ()<br />

Set cnnXLS = Nothing<br />

Set cnnMDB = Nothing<br />

Set cnnDBF = Nothing<br />

Set rstXLS = Nothing<br />

Set rstMDB = Nothing<br />

Set rstDBF = Nothing<br />

End Sub<br />

Sub ВсеПоля ()<br />

Set базаДанных = CurrentDb<br />

Set таблица = базаДанных!t3<br />

For Each поле In таблица.Fields<br />

строка = строка & Chr(13) & поле.Name<br />

Next поле<br />

MsgBox строка<br />

End Sub<br />

Sub ТекущаяЗаписьADO ()<br />

Dim rst As New ADODB.Recordset<br />

rst.Open "Сотрудники", CurrentProject.Connection<br />

Debug.Print rst.Fields ("Кто"), rst.Fields ("Когда")<br />

rst.Close<br />

End Sub<br />

Sub Записи1ADO ()<br />

Dim rst As New ADODB.Recordset<br />

rst.Open "ЗапросСотрудники", CurrentProject.Connection<br />

<strong>на</strong>бор.MoveNext<br />

Debug.Print rst.Fields ("Кто"), rst.Fields ("Когда")<br />

<strong>на</strong>бор.Move 4<br />

Debug.Print rst.Fields ("Кто"), rst.Fields ("Когда")<br />

Set rst = Nothing<br />

End Sub<br />

Sub Записи2ADO ()<br />

Dim cnn As New ADODB.Connection, rst As New ADODB.Recordset


18<br />

cnn.Open "DBQ=D:\;Driver={Microsoft dBase Driver (*.dbf)}"<br />

With rst<br />

.Open "Сотрудники", cnn<br />

For i = 0 To .Fields.Count - 1<br />

temp = temp & .Fields (i).Name & " "<br />

Next<br />

temp = temp & vbCr<br />

Do While Not .EOF<br />

For i = 0 To .Fields.Count - 1<br />

temp = temp & rst.Fields (i) & " "<br />

Next<br />

temp = temp & vbCr<br />

.MoveNext<br />

Loop<br />

MsgBox "Всего в " & .Source & " полей: " & .Fields.Count & _<br />

vbCr & "Всего записей: " & .RecordCount & vbCr & temp<br />

End Sub<br />

Sub ПозиционированиеADO ()<br />

Dim rst As New ADODB.Recordset<br />

rst.Open "Сотрудники", CurrentProject.Connection, adOpenStatic<br />

Do While Not rst.EOF<br />

строка = rst!Кто & " " & rst.AbsolutePosition & _<br />

" из " & rst.RecordCount<br />

If MsgBox (строка, vbOKCancel) = vbCancel Then Exit Do<br />

rst.MoveNext<br />

Loop<br />

End Sub<br />

Sub ОбъектCommand ()<br />

Dim rst As ADODB.Recordset, cmd As ADODB.Command<br />

Dim строка As String, счетчик As Integer<br />

Set rst = New ADODB.Recordset<br />

Set cmd = New ADODB.Command<br />

Set cmd.ActiveConnection = CurrentProject.Connection<br />

cmd.CommandText = _<br />

"SELECT Кто, Сколько FROM Сотрудники WHERE Сколько>1100"<br />

rst.CursorLocation = adUseClient<br />

Set rst = cmd.Execute ()<br />

Do While Not rst.EOF<br />

счетчик = счетчик + 1<br />

строка = строка & Str (счетчик) & " " & rst!Кто & " " & rst!Сколько & vbCr<br />

rst.MoveNext<br />

Loop<br />

MsgBox строка & "Всего: " & счетчик<br />

rst.Close<br />

Set cmd = Nothing<br />

End Sub<br />

Для изменения <strong>данных</strong> следует с<strong>на</strong>чала сделать запись текущей. В<br />

модели ADO изменения <strong>данных</strong> программируются проще, чем в DAO, так


19<br />

как используется обычный оператор присваивания с последующим<br />

обновлением.<br />

В модели ADO используется отличный от DAO синтаксис поиска:<br />

• объектRecordset.Seek (з<strong>на</strong>ченияКлюча, параметрыПоиска)<br />

• Find (Критерии, Пропуск, <strong>на</strong>правлениеПоиска, Старт)<br />

где аргументы указывают массив переменных искомого з<strong>на</strong>чения и<br />

константный тип сравнения, число пропускаемых строк и <strong>на</strong>правление.<br />

Sub ПравкаADO ()<br />

Dim rst As New ADODB.Recordset<br />

строкаSQL = "SELECT * FROM Сотрудники WHERE Сколько


20<br />

.Open "Сотрудники", CurrentProject.Connection, _<br />

adOpenDynamic, adLockPessimistic<br />

.Find "Кто = 'Гуринов'"<br />

.Fields ("Зачем") = "Отпуск"<br />

.AddNew<br />

.Fields ("Кто") = "Архипов"<br />

.Update<br />

.Close<br />

End With<br />

End Sub<br />

Sub УдалениеADO ()<br />

Dim rst As New ADODB.Recordset<br />

rst.Open "Сотрудники", CurrentProject.Connection, _<br />

adOpenStatic, adLockOptimistic<br />

rst.Find "Кто = 'Гуринов'"<br />

rst.Delete adAffectCurrent<br />

rst.Update<br />

rst.Close<br />

End Sub<br />

Public Sub УдалениеЗаписиADO()<br />

Dim rst As New ADODB.Recordset<br />

rst.Open "SELECT * FROM Сотрудники " & _<br />

"WHERE Сколько < 200", CurrentProject.Connection, _<br />

adOpenStatic, adLockOptimistic<br />

строка = rst.RecordCount & vbCr<br />

Do While Not rst.EOF<br />

строка = строка & rst!Кто & vbCr<br />

rst.MoveNext<br />

Loop<br />

MsgBox строка<br />

строка = UCase (InputBox ("Кого удалить"))<br />

rst.Filter = "Кто = '" & строка & "'"<br />

rst.Delete<br />

rst.UpdateBatch<br />

rst.Filter = adFilterNone<br />

rst.Requery<br />

строка = "После удаления осталось " & rst.RecordCount & vbCr<br />

Do While Not rst.EOF<br />

строка = строка & rst!Кто & vbCr<br />

rst.MoveNext<br />

Loop<br />

MsgBox строка<br />

rst.Close<br />

End Sub<br />

Sub ЗапросыADO ()<br />

Dim <strong>на</strong>бор As New ADODB.Recordset<br />

<strong>на</strong>бор.Open "Сотр", CurrentProject.Connection, adOpenStatic, adLockOptimistic<br />

где = "Сколько < 200"<br />

DoCmd.RunSQL _


21<br />

"UPDATE Сотр SET Сколько = 5 WHERE " & где<br />

DoCmd.RunSQL _<br />

"UPDATE Сотр SET Кто = 'LG' WHERE " & где<br />

Set <strong>на</strong>бор = Nothing<br />

End Sub<br />

Визуальное программирование в <strong>Access</strong><br />

Для работы с формами и отчетами используется библиотека <strong>Access</strong> с<br />

базовым классом Application. Основными методами Application являются:<br />

Метод<br />

Наз<strong>на</strong>чение<br />

CloseCurrentDatabase Закрывает текущую базу <strong>данных</strong> из другой базы<br />

NewCurrentDatabase Создает новый объект Database из другого приложения<br />

OpenCurrentDatabase Открывает в качестве текущей базы объект Database<br />

Quit<br />

Закрывает <strong>Access</strong><br />

Run<br />

Запускает процедуру <strong>Access</strong> из другого приложения<br />

RunCommand Запускает команду меню или панели инструментов<br />

Входящее в <strong>Access</strong> семейство Forms (Формы) содержит формы и их<br />

объекты, при<strong>на</strong>длежащие классу Controls (Элементы управления). Семейство<br />

Reports (Отчеты) включает все отчеты приложения и объекты отчетов того<br />

же класса Controls. Семейство Modules (Модули) объединяет все стандартные<br />

модули и модули авторских классов, а также модули, связанные с формами и<br />

отчетами. Для работы с ок<strong>на</strong>ми используется класс Screen. А класс DoCmd<br />

позволяет обращаться из модулей к стандартным средствам <strong>Access</strong>.<br />

Схема обращения к чле<strong>на</strong>м библиотеки классов <strong>Access</strong>:<br />

имяКласса!имяОбъекта[.имяЭлементаУправления].Член<br />

Открытие форм и отчетов выполняется методами OpenForm и<br />

OpenReport объекта DoCmd:<br />

• DoCmd.OpenForm Объект [, режимВывода] [, Запрос] _<br />

[, условиеОтбора] [, режимДанных] [, режимОк<strong>на</strong>] _<br />

[, аргументыОткрытия]<br />

• DoCmd.OpenReport Объект [, режимВывода] [, Запрос] _<br />

[, условиеОтбора] [, режимДанных] [, режимОк<strong>на</strong>] _<br />

[, аргументыОткрытия]<br />

Обращение к объектам форм и отчетов выполняется по схемам:<br />

• [Forms! Форма!] Объект


22<br />

• [Reports! Отчет!] Объект<br />

• Forms («имяОбъекта»)<br />

• Reports («имяОбъекта»)<br />

• Forms (индексОбъекта)<br />

• Reports (индексОбъекта)<br />

• Forms (ссылоч<strong>на</strong>яПеремен<strong>на</strong>я)<br />

• Reports (ссылоч<strong>на</strong>яПеремен<strong>на</strong>я)<br />

Точка отделяет объект от его свойства или метода, а также разделяет объекты<br />

подчиненной формы (отчета):<br />

• [Forms! Форма!] [Объект].[свойствоИлиМетод]<br />

• [Reports! Отчет!] [Объект].[свойствоИлиМетод]<br />

• [Forms!Глав<strong>на</strong>яФорма!]Подчинен<strong>на</strong>яФорма.[Form!] Объект<br />

• [Forms!Глав<strong>на</strong>яФорма!]Подчинен<strong>на</strong>яФорма.ееИсточникДанных<br />

Обращение к активным объектам класса Screen в ряде случаев заменяют их<br />

свойствами ActiveDataSheet, ActiveForm, ActiveControl, PreviousControl,<br />

Application, Parent. А для ссылки <strong>на</strong> активную форму или отчет из модулей<br />

их классов удобно использовать конструкции<br />

• Me.Член<br />

• Me!Объект<br />

Закрытие объектов выполняется методом Close класса <strong>Access</strong> и объекта<br />

DoCmd, а выход из <strong>Access</strong> — методом Quit:<br />

DoCmd.Close [типОбъекта, имяОбъекта], [параметрСохранения]<br />

• Application.Quit [параметрСохранения]<br />

• DoCmd.Quit [параметрСохранения]<br />

где типОбъекта и параметрСохранения выражаются встроенными<br />

константами.<br />

Примеры<br />

Sub ОткрытиеФормы<strong>Access</strong> ()<br />

DoCmd.OpenForm "Форма Таблицы1"<br />

MsgBox Forms![Форма Таблицы1].Caption<br />

End Sub<br />

Sub ОткрытиеФорм<strong>Access</strong> ()<br />

On Error GoTo ошибка


23<br />

Имя = InputBox ("Какую открыть форму")<br />

DoCmd.OpenForm Имя<br />

Exit Sub<br />

ошибка:<br />

MsgBox "Ошибка " & Err, vbExclamation<br />

Exit Sub<br />

End Sub<br />

Sub СвойстваФормы<strong>Access</strong> ()<br />

DoCmd.OpenForm FormName:="Мы", view:=acDesign, windowmode:=acHidden<br />

With Forms!Мы<br />

.Caption = "Сведения о клиентах"<br />

.Modal = True<br />

.DefaultView = 1<br />

.AllowEdits = False<br />

.AutoResize = False<br />

.AutoCenter = True<br />

.Width = 300<br />

.Picture = "d:\ f1.bmp"<br />

.Tag = "0"<br />

.OnActivate = "=FunctionName ()"<br />

.OnCurrent = "[Процедура обработки событий]"<br />

.OnClose = "Макрос"<br />

End With<br />

DoCmd.OpenForm "Мы"<br />

End Sub<br />

Sub ОткрытиеОтчета<strong>Access</strong> ()<br />

DoCmd.OpenForm "Выставка"<br />

ответ = MsgBox ("Вывести отчет ", vbYesNoCancel)<br />

If ответ = vbYes Then DoCmd.OpenReport "Выставка", acPreview<br />

MsgBox Screen.ActiveReport.Name<br />

End Sub<br />

Sub ЗакрытьФормуОтчет ()<br />

DoCmd.OpenForm “Сотрудники”,,, “Должность = ‘дилер’ ”<br />

MsgBox Forms (“Сотрудники”).Caption<br />

DoCmd.Close acForm, "Сотрудники", acPrompt<br />

DoCmd.OpenReport “Сотрудники”, acViewPreview<br />

MsgBox Reports!Сотрудники.Page<br />

DoCmd.Close Save:=acSaveYes<br />

End Sub<br />

Private Sub Form_Current ()<br />

Form_имяФормы.Caption = Time<br />

MsgBox Me.Name + Me.Tag<br />

End Sub<br />

Function ButtonOpenNextForm (fName As String)<br />

Dim имяЭтойФормы As String<br />

имяЭтойФормы = Screen.ActiveForm.Name<br />

Screen.ActiveForm.Visible = False<br />

DoCmd.OpenForm fName


24<br />

Screen.ActiveForm.Tag = имяЭтойФормы<br />

End Function<br />

Function ButtonCloseAndReturn ()<br />

Dim имяПредыдущейФормы As String<br />

If Screen.ActiveForm.Tag = "" Then<br />

DoCmd.Close<br />

Else<br />

имяПредыдущейФормы = Screen.ActiveForm.Tag<br />

DoCmd.Close<br />

Forms (имяПредыдущейФормы).Visible = True<br />

End If<br />

End Function<br />

Function КонецРаботы<strong>Access</strong> ()<br />

ответ = MsgBox ("Закончить работу", vbYesNoCancel + vbQuestion)<br />

Select Case ответ<br />

Case vbYes<br />

DoCmd.Quit acPrompt<br />

КонецРаботы<strong>Access</strong> = True<br />

Case vbNo<br />

DoCmd.Close acForm, "Форма Таблицы1", acSaveYes<br />

КонецРаботы<strong>Access</strong> = False<br />

Case vbCancel<br />

КонецРаботы<strong>Access</strong> = False<br />

End Select<br />

End Function<br />

В следующей таблице приведены <strong>на</strong>иболее общие свойства объектов<br />

Form и Report (обоз<strong>на</strong>чения: o — объект, i — целый, b — логический, s —<br />

строковый, ro — только чтение):<br />

Свойство Тип Описание<br />

ActiveControl ro, o Активный элемент управления открытой формы<br />

Count<br />

ro, i Число открытых элементов семейства<br />

CurrentRecord ro, i Номер текущей записи формы<br />

Cycle i AllRecords, CurrentRecord или CurrentPage в форме<br />

Dirty<br />

ro, b Измене<strong>на</strong> ли текущая запись после сохранения<br />

Form<br />

ro, o Ссылка <strong>на</strong> форму<br />

HasData ro, i В отчете есть данные (-1) или нет <strong>данных</strong> (0)<br />

Me<br />

ro, o Сама форма или отчет<br />

MenuBar s Имя строки меню или стандартное меню («»)<br />

Modal b Модаль<strong>на</strong>я ли форма<br />

NewRecord ro, b Является ли текущая запись формы новой<br />

OrderBy s Список полей, определящий порядок сортировки<br />

Painting b Необходимо ли перерисовать форму


25<br />

Picture<br />

bmp Имя файла фо<strong>на</strong><br />

PopUp b Всплывающая ли форма<br />

RecordSetClone ro, o Доступ к свойствам записей RecordSource<br />

RecordSource s Источник <strong>данных</strong>: таблица или запрос<br />

Report<br />

ro, o Ссылка <strong>на</strong> отчет<br />

Section<br />

ro, o Доступ к области или ее элементу управления<br />

ShortcutMenuBar s Имя контекстного меню или стандартное («»)<br />

StatusBarText s Текст строки состояния формы<br />

TabIndex i Номер элемента управления формы<br />

ToolBar s Имя панели инструментов или стандарт<strong>на</strong>я («»)<br />

Visible b Отображается ли <strong>на</strong> экране<br />

Некоторые свойства являются свойствами по умолчанию, и их можно<br />

опускать:<br />

Свойство Имя объекта Объект<br />

Value Флажок CheckBox<br />

Text Поле со списком ComboBox<br />

Text Список ListBox<br />

Value Переключатель OptionButton<br />

OptionValue Группа переключателей OptionGroup<br />

Value Поле TextBox<br />

Value Переключатель ToggleButton<br />

Некоторые методы объектов Form:<br />

Метод<br />

GoToPage<br />

Recalc<br />

Refresh<br />

Repaint<br />

Requery<br />

SetFocus<br />

Undo<br />

Действие<br />

Передает фокус первому элементу управления активной формы<br />

Обновляет вычисляемые элементы, но не функции SQL<br />

Обновляет записи без учета добавлений и удалений<br />

Обновляет экран и завершает вычисления<br />

Обновляет источник <strong>данных</strong> формы<br />

Передает фокус элементу, ранее последним им владевшему<br />

Отменяет изменения в форме<br />

Обновление объектов, активных таблиц и запросов выполняется<br />

методом Requery:<br />

• имяОбъекта.Requery<br />

• DoCmd.Requery


26<br />

Событие До обновления (BeforeUpdate) возникает в момент<br />

перемещения с записи <strong>на</strong> запись. Если пользователь изменяет запись,<br />

свойство формы Dirty становится истинным, и если после этого аргументу<br />

Cancel присвоить з<strong>на</strong>чение True, событие отменяется. Метод Undo<br />

восста<strong>на</strong>вливает исходные данные. Событие После обновления (AfterUpdate)<br />

используется для выполнения определенных действий в зависимости от<br />

введенных в поле з<strong>на</strong>чений. При передаче фокуса от одного элемента<br />

управления к другому возникают события Вход (Enter), соответствующее<br />

приему фокуса, и Выход (Exit), соответствующее его потере.<br />

Для выявления идентичных объектов можно использовать оператор Is.<br />

Он определяет логический результат как Null или Not Null.<br />

Для ссылок из формы или отчета <strong>на</strong> объект RecordSet используется<br />

свойство RecordSetClone. З<strong>на</strong>чение этого свойства формы определяет копию<br />

записей базовой таблицы или запроса, указанных в свойстве Источник<br />

записей формы. В частности, если форма основа<strong>на</strong> <strong>на</strong> запросе, то обращение<br />

к свойству RecordSetClone эквивалентно созданию копии объекта RecordSet с<br />

помощью того же запроса. Если к форме будет дополнительно применен<br />

фильтр, то объект RecordSet создается с учетом фильтра:<br />

Примеры<br />

Sub СвободныеЭлементы<strong>Access</strong>()<br />

Dim <strong>на</strong>дпись As Object, поле As Object<br />

DoCmd.OpenForm "Форма1"<br />

Set <strong>на</strong>дпись = Forms!Форма1.Надпись1<br />

Set поле = Forms!Форма1.Поле0<br />

<strong>на</strong>дпись.Caption = поле.Text<br />

End Sub<br />

Sub ПолеФормы<strong>Access</strong> ()<br />

Dim поле As Control<br />

DoCmd.OpenForm "Клиенты"<br />

Set поле = Forms!Клиенты![Обращаться к]<br />

поле = "Сергей Петров"<br />

Forms!Клиенты.Refresh<br />

End Sub<br />

Sub ОбновлениеЧерезФорму<strong>Access</strong> ()<br />

DoCmd.OpenForm "Сотрудники", , , "Фамилия = 'Иванов'"<br />

Set где = Forms!Сотрудники<br />

If IsNull (где.оклад) Then где.оклад = 0<br />

где.оклад = InputBox ("Можно заменить " & Str (где.оклад), , где.оклад)<br />

DoCmd.Requery<br />

End Sub<br />

Sub СтильПоляФормы ()<br />

DoCmd.OpenForm "Клиенты", acDesign, , , , acHidden<br />

Set поле = Forms!Клиенты!Имя<br />

поле.FontSize = 14


27<br />

поле.FontName = "Times New Roman Cyr"<br />

поле.Enabled = False<br />

DoCmd.Save acForm, "Клиенты"<br />

DoCmd.OpenForm "Клиенты"<br />

End Sub<br />

Sub Надпись<strong>Access</strong> ()<br />

Set форма = Forms![Сотрудники]<br />

With форма<br />

.[ОкладНадпись].Caption = "Должность"<br />

.Controls![ОкладНадпись].FontName = "Arial Cyr"<br />

.Оклад.SetFocus<br />

.Оклад.Requery<br />

.Дата.Enabled = False<br />

End With<br />

End Sub<br />

Sub Form_Current ()<br />

текст = Me![Поле1] Like "К*"<br />

If текст Then MsgBox "Кузнецов!" Else MsgBox "Не он"<br />

End Sub<br />

Sub Кнопка_ Click ()<br />

On Error GoTo сообщение<br />

Err.Clear<br />

With Me<br />

!Премия.SetFocus<br />

память = !Премия.Text<br />

!Оклад.SetFocus<br />

!Оклад.Text = Val (!Оклад.Text) + Val (память)<br />

.Refresh<br />

End With<br />

Exit Sub<br />

сообщение:<br />

MsgBox "Ошибка номер " & Err<br />

End Sub<br />

Sub КнопкаОшибки_Click ()<br />

On Error GoTo сообщение<br />

Err.Clear<br />

число = InputBox ("Введите число")<br />

сумма = 50 / число<br />

Me!Оклад.SetFocus<br />

Me!Оклад.Text = сумма<br />

Me.Refresh<br />

Exit Sub<br />

сообщение:<br />

плохо = "Ошибка № " & Str (Err.Number) & " возникла в " _<br />

& Err.Source & Chr (13) & Err.Description


28<br />

MsgBox плохо, , "Ошибка"<br />

End Sub<br />

Sub Форма1<strong>Access</strong>_BeforeUpdate (Cancel As Integer)<br />

If Me.Dirty Then<br />

If MsgBox ("Сохранить изменения", vbYesNo) = vbNo Then Me.Undo<br />

End If<br />

End Sub<br />

Sub Форма1<strong>Access</strong>_AfterUpdate ()<br />

MsgBox "В " & Me.Name & “ кое-что изменилось ;-)”<br />

End Sub<br />

Sub Навигация<strong>Access</strong>()<br />

DoCmd.OpenForm "Сотрудники"<br />

Set форма = Forms!Сотрудники<br />

DoCmd.GoToRecord , , acLast<br />

форма.Надпись.Caption = Str (форма.CurrentRecord)<br />

DoCmd.GoToRecord , , acNewRec<br />

форма.Фамилия = InputBox ("Следующий")<br />

форма.Refresh<br />

End Sub<br />

Function Подчинен<strong>на</strong>яФорма<strong>Access</strong> ()<br />

DoCmd.OpenForm "Глав<strong>на</strong>я"<br />

DoCmd.GoToControl "Подчинен<strong>на</strong>я форма"<br />

DoCmd.GoToRecord , , acNewRec<br />

With Forms!Глав<strong>на</strong>я<br />

![Подчинен<strong>на</strong>я форма]!ПодчТовар = !КлиентыТовар<br />

![Подчинен<strong>на</strong>я форма]!ПодчНазвание = !КлиентыНазвание<br />

![Подчинен<strong>на</strong>я форма]!ПодчЦе<strong>на</strong> = !КлиентыЦе<strong>на</strong><br />

End With<br />

Forms!Глав<strong>на</strong>я.Refresh<br />

End Function<br />

Sub Дни_Click ()<br />

On Error GoTo конец<br />

Dim день (1) As Date, ошибки As Integer, поле As Object<br />

Set поле = Me!дата<br />

DoCmd.GoToRecord , , acFirst<br />

Do While 1<br />

день (0) = поле<br />

DoCmd.GoToRecord , , acNext<br />

день (1) = поле<br />

If DateDiff ("d", день (0), день (1)) 1 Then<br />

MsgBox день (0) & " или " & день (1) & " неверно"<br />

ошибки = ошибки + 1<br />

End If<br />

Loop<br />

конец:<br />

MsgBox "Всего ошибок: " & Str (ошибки)<br />

End Sub


29<br />

Sub ОткрытыеОтчеты ()<br />

список = "Открыто отчетов: " & Reports.Count<br />

For Each отчеты In Reports<br />

список = список & Chr (13) & отчеты.Name<br />

For Each объекты In отчеты.Controls<br />

список = список & Chr(13) & "Объект " & объекты.Name<br />

Next объекты<br />

Next отчеты<br />

MsgBox список<br />

End Sub<br />

Sub А<strong>на</strong>лизТаблицыЧерезФорму ()<br />

DoCmd.OpenForm "Выставка"<br />

MsgBox Forms (“Выставка”).RecordsetClone.RecordCount & " записей "<br />

End Sub<br />

Sub <strong>Access</strong>Form_Open ()<br />

If Me.RecordsetClone.RecordCount = 0 Then<br />

MsgBox "Записей нет", vbInformation<br />

Else<br />

MsgBox Me.RecordsetClone.RecordCount & " записей"<br />

End If<br />

End Sub<br />

Sub ФормаADO ()<br />

Dim cnn As New ADODB.Connection, rst As New ADODB.Recordset<br />

cnn.Open "DBQ=D:\VAL\<strong>Access</strong>\<strong>Access</strong>03\Сотрудники.xls;" _<br />

& "Driver={Microsoft Excel Driver (*.xls)}"<br />

rst.CursorType = adOpenStatic<br />

rst.Open Лист1, cnn<br />

DoCmd.OpenForm “Form1”<br />

Set Forms (“Form1”).Recordset = rst<br />

Forms (“Form1”).Controls ("Надпись").Caption = rst.RecordCount<br />

Forms (“Form1”).Controls ("Список").RowSource = "select * from rst.Source"<br />

End Sub<br />

Public cnnDBF As New ADODB.Connection<br />

Public rstDBF As New ADODB.Recordset<br />

Sub ПодключениеКФормеADO ()<br />

ConnectStr = "DBQ=D:\;Driver={Microsoft dBase Driver (*.dbf)}"<br />

cnnDBF.Open ConnectStr<br />

With rstDBF<br />

.Open "select * from " & ВыборФайла () & _<br />

" where [отдел]=15", cnnDBF, adOpenDynamic, adLockOptimistic<br />

MsgBox ДобавитьУдалить ()<br />

.Close<br />

.Open "select * from " & ВыборФайла () _<br />

& " where [отдел]=15", cnnDBF, adOpenStatic, adLockPessimistic<br />

End With<br />

DoCmd.OpenForm "фILM_Test"


30<br />

Set Forms ("фILM_Test").Recordset = rstDBF<br />

End Sub<br />

Function ВыборФайла () As String<br />

Select Case Forms ("фILM_Test").Группа10<br />

Case 1:<br />

ВыборФайла = "ILMTest1"<br />

Forms ("фILM_Test").Caption = "ILMTest1"<br />

Case 2:<br />

ВыборФайла = "ILMTest2"<br />

Forms ("фILM_Test").Caption = "ILMTest2"<br />

Case 3: ВыборФайла = "ILMTest3"<br />

Forms ("фILM_Test").Caption = "ILMTest3"<br />

End Select<br />

End Function<br />

Function ДобавитьУдалить () As String<br />

With rstDBF<br />

.AddNew<br />

.Fields ("КОГДА") = #1/31/2003#<br />

.Fields ("ОТДЕЛ") = 15<br />

.AddNew<br />

.Fields ("КОГДА") = "31.1.03"<br />

.Fields ("ОТДЕЛ") = 15<br />

.MoveFirst<br />

Do While Not .EOF<br />

myField = .Fields ("КОГДА")<br />

If DateDiff ("yyyy", myField, Date) > 60 Then<br />

.Delete<br />

cnt = cnt + 1<br />

End If<br />

.MoveNext<br />

Loop<br />

End With<br />

AddDelete = "Выполнено " & cnt & " удалений"<br />

End Function<br />

Sub ЗапросSQL ()<br />

DoCmd.OpenForm "Сотрудники"<br />

DoCmd.RunSQL “UPDATE Сотрудники SET Родился = #01/12/02#” _<br />

& “WHERE Номер = 28”<br />

DoCmd.RunSQL “DELETE FROM Сотрудники WHERE Родился = #01/12/02#”<br />

DoCmd.RunSQL “INSERT INTO Сотрудники (ФИО, Родился, Должность)” _<br />

& “VALUES (‘Кто-то’, #01/12/12#, ‘Дилер’)”<br />

DoCmd.Requery<br />

End Sub<br />

Sub ПеренумероватьЗаписи ()<br />

DoCmd.RunSQL "ALTER TABLE Сотрудники DROP COLUMN z"<br />

DoCmd.RunSQL "ALTER TABLE Сотрудники ADD COLUMN z COUNTER"


31<br />

DoCmd.OpenForm "Сотрудники"<br />

End Sub<br />

Sub Запрос<strong>Access</strong> ()<br />

DoCmd.SetWarnings False<br />

DoCmd.OpenForm "Сотрудники", acDesign, , , , acHidden<br />

DoCmd.OpenQuery "Запрос1"<br />

DoCmd.Close acForm, "Сотрудники"<br />

DoCmd.SetWarnings True<br />

End Sub<br />

Меню<br />

Меню создаются и редактируются под управлением редактора меню<br />

или с помощью процедур, размещаемых в модулях. Редактор меню<br />

представлен вкладкой Команды меню Вид .Панели инструментов<br />

.Настройка…<br />

Различают встроенные меню приложения и авторские меню<br />

пользователя. Каждому пункту авторского меню соответствует<br />

индивидуальный макрос или функция. Редактор меню позволяет удалять<br />

любой пункт меню, открыв его контекстное меню и выбрав из него Сброс<br />

или Удалить при открытом окне Настройка. При этом встроенные меню не<br />

удаляются, а скрываются. В любое меню можно добавить новый пункт через<br />

вкладку Команды меню Вид .Панели инструментов .Настройка,<br />

перетащив необходимый элемент из списка Команды в меню.<br />

Для программирования строк меню используются объекты классов<br />

CommandBars и CommandBar из библиотеки Microsoft Office. Первый из<br />

классов хранит все строки встроенных меню. Он служит инструментом<br />

использования меню приложения и создания авторских меню. Второй класс<br />

представляет все пункты конкретного меню. Он служит инструментом<br />

использования пунктов меню приложения и создания авторских пунктов.<br />

Ссылки <strong>на</strong> пункты меню определяются свойством Controls.<br />

Для отображения контекстных меню используется метод ShowPopup, а<br />

для удаления всех новых меню, не выведенных <strong>на</strong> экран, – методы Delete и<br />

Reset.<br />

Примеры<br />

Sub ВсеСтрокиМеню ()<br />

For Each строкаМеню In CommandBars<br />

Debug.Print строкаМеню.Index, " ", строкаМеню.Name<br />

Next<br />

End Sub<br />

Sub ВсеПунктыМеню ()<br />

For Each пункт In CommandBars ("Menu Bar").Controls<br />

список = список & пункт.Index & " " & пункт.Caption & Chr(13)


32<br />

Next<br />

MsgBox список<br />

End Sub<br />

Sub ЕщеСтрокаМеню ()<br />

Set новоеМеню = CommandBars.Add (Name:="Игры", _<br />

Position:=msoBarFloating, MenuBar:=False, Temporary:=True)<br />

новоеМеню.Visible = True<br />

End Sub<br />

Sub НаполнениеСтрокиМеню ()<br />

Set меню = CommandBars (CommandBars.Count)<br />

Set новыйПункт = меню.Controls.Add (Type:=msoControlPopup)<br />

новыйПункт.Caption = "Информация"<br />

Set подпункт1 = новыйПункт.Controls.Add (Type:=msoControlPopup)<br />

подпункт1.Caption = "О меню"<br />

Set подпункт2 = новыйПункт.Controls.Add (Type:=msoControlPopup)<br />

With подпункт2<br />

.Caption = "О панелях"<br />

.Enabled = True<br />

.OnAction = "процедураИлиМакрос"<br />

End With<br />

End Sub<br />

Sub УдалениеМеню ()<br />

For Each меню In CommandBars<br />

If Not меню.BuiltIn And Not меню.Visible Then меню.Delete<br />

Next<br />

End Sub<br />

Sub ВосстановлениеМеню ()<br />

On Error Resume Next<br />

For i = 1 To CommandBars.Count<br />

CommandBars (i).Reset<br />

Next<br />

End Sub<br />

Панели инструментов<br />

<strong>VBA</strong> позволяет изменить изображение любой кнопки панели<br />

инструментов с помощью меню Вид .Панели инструментов .Настройка.<br />

При программировании панели инструментов рассматриваются как<br />

разновидности меню.<br />

Примеры<br />

Sub НоваяПанельИнструментов ()<br />

On Error GoTo ошибка<br />

Dim новаяПанель As CommandBar<br />

Set новаяПанель = CommandBars.Add (Name:="Игры", _<br />

Position:=msoBarFloating, MenuBar:=False, Temporary:=True)


33<br />

With новаяПанель.Controls<br />

.Add Type:=msoControlEdit<br />

.Add Type:=msoControlButton , Id:=4<br />

.Add Type:=msoControlButton , Id:=21<br />

.Add Type:=msoControlDropdown<br />

.Add Type:=msoControlComboBox<br />

End With<br />

новаяПанель.Controls (1).OnAction = "мойМакрос"<br />

новаяПанель.Visible = True<br />

номерПанели = CommandBars.Count<br />

MsgBox "Перед вами панель " & новаяПанель.Name _<br />

& " номер " & номерПанели<br />

ошибка:<br />

CommandBars ("Игры").Delete<br />

End Sub<br />

Sub НовыйЭлемент ()<br />

On Error GoTo ошибка<br />

Dim панель As CommandBar<br />

Dim элемент As CommandBarComboBox<br />

Set панель = CommandBars (3)<br />

Set элемент = панель.Controls.Add (Type:=msoControlDropdown)<br />

With элемент<br />

.AddItem "Кофе", 1<br />

.AddItem "Чай", 2<br />

.AddItem "Сок", 3<br />

.DropDownWidth = 75<br />

.DropDownLines = 3<br />

.ListIndex = 3<br />

End With<br />

панель.Visible = True<br />

ошибка:<br />

элемент.Delete<br />

End Sub<br />

Sub ПанелиИнструментов ()<br />

For Each панель In CommandBars<br />

If панель.Index > 2 And панель.Index < 19 Then панель.Visible = False<br />

Next панель<br />

MsgBox "Все панели инструментов скрыты." & Chr (13) & _<br />

"Сейчас они будут последовательно возвращаться"<br />

For Each панель In CommandBars<br />

If панель.Index > 2 And панель.Index < 19 Then<br />

панель.Visible = True<br />

MsgBox "Это панель " & панель.Name<br />

End If<br />

Next панель<br />

If MsgBox ("Убрать лишние ", vbYesNo) = vbYes Then<br />

For счетчик = 18 To 5 Step -1<br />

CommandBars (счетчик).Visible = False<br />

Next счетчик


34<br />

End If<br />

End Sub<br />

Началь<strong>на</strong>я установка интерфейса<br />

База <strong>данных</strong> <strong>Access</strong> открывается в соответствии с <strong>на</strong>стройками меню<br />

Сервис .Параметры запуска или макросом AutoExec.<br />

Примеры<br />

Sub ПараметрыЗапуска ()<br />

ЗадатьСвойство "StartupForm", dbText, "МояФорма"<br />

ЗадатьСвойство "AppTitle", dbText, "Моя форма"<br />

ЗадатьСвойство "StartupShowDBWindow", dbBoolean, False<br />

ЗадатьСвойство "StartupShowStatusBar", dbBoolean, False<br />

ЗадатьСвойство "AllowBuiltinToolbars", dbBoolean, True<br />

ЗадатьСвойство "AllowFullMenus", dbBoolean, True<br />

ЗадатьСвойство "AllowBreakIntoCode", dbBoolean, False<br />

ЗадатьСвойство "AllowSpecialKeys", dbBoolean, True<br />

ЗадатьСвойство "AllowBypassKey", dbBoolean, TrueEnd Sub<br />

MsgBox(“OK”)<br />

End Sub<br />

Function ЗадатьСвойство (имяСвойства As String, типСвойства As Variant, _<br />

з<strong>на</strong>чениеСвойства As Variant) As Integer<br />

Const conPropNotFoundError = 3270<br />

On Error GoTo еслиНетТакогоСвойства<br />

CurrentDb.Properties (имяСвойства) = з<strong>на</strong>чениеСвойства<br />

ЗадатьСвойство = True<br />

конец:<br />

Exit Function<br />

еслиНетТакогоСвойства:<br />

If Err = conPropNotFoundError Then ' свойство не установлено<br />

Set свойство = CurrentDb.CreateProperty (имяСвойства, _<br />

типСвойства, з<strong>на</strong>чениеСвойства)<br />

CurrentDb.Properties.Append свойство<br />

Resume Next<br />

Else<br />

' неяс<strong>на</strong>я ошибка<br />

ЗадатьСвойство = False<br />

Resume конец<br />

End If<br />

End Function<br />

Sub АнтиШифт ()<br />

On Error GoTo добавитьСвойство<br />

If MsgBox ("Нужен ли Шифт", vbYesNo) = vbYes Then<br />

нуженЛи = True<br />

Else<br />

нуженЛи = False


35<br />

End If<br />

CurrentDb.Properties ("AllowBypassKey") = нуженЛи<br />

MsgBox "Свойство установлено"<br />

Exit Sub<br />

добавитьСвойство:<br />

CurrentDb.Properties.Append _<br />

CurrentDb.CreateProperty ("AllowBypassKey", DbBoolean, нуженЛи)<br />

MsgBox "Свойство добавлено и установлено"<br />

End Sub<br />

Sub УдалитьСвойство ()<br />

On Error GoTo нетТакогоСвойства<br />

CurrentDb.Properties.Delete "AllowBypassKey"<br />

Exit Sub<br />

нетТакогоСвойства:<br />

MsgBox "Нет такого свойства"<br />

End Sub

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!