Справочники. Часть 3.

Источник: leadersoft

В то время, когда составлялась данная рассылка, Валерий Крук опять удивил общественность, предложив очень интересную идею. Вкратце суть его предложения в следующем:
Часто бывает, что вариантов для подстановок значений в поле формы не много и поэтому заводить для этого отдельную таблицу - справочник не желательно. Вставлять же заранее все значения в поле со списком тоже не выход, ведь иногда приходится менять содержимое списка. Валерий же предлагает компромисс - объединить справочные данные для нескольких списков в одну таблицу. А заодно предложил оригинальный интерфейс для ввода/редактирования данных.
Подробно рассказывать я не буду, иначе получится плагиат, желающие могут ознакомится с примером по ссылке http://am.rusimport.ru/MSAccess/topic.aspx?id=598

    В предыдущей статье рассматривался пример добавления отсутствующего значения в список подстановок. Но данные не сохранялись, потому что для этого нужна справочная таблица. Теперь я покажу аналогичный пример, но уже с использованием справочной таблицы, тем самым решится проблема сохранения нового значения в справочнике. Добавлять данные, так же как и в предыдущем примере будем программно. Для этого воспользуемся DAO - Data Access Objects - объектная модель доступа к данным. Объекты доступа к данным создавались, как объектно - ориентированный интерфейс для ядра баз данных Jet фирмы Microsoft как раз для того, чтобы можно было программно вносить, изменять, удалять данные в таблицах.
    Создадим функцию AppendLookupTable и поместим в общий модуль, чтобы ее можно было вызывать из разных форм, для разных полей со списками, а не только для конкретного.

    Для работы с таблицей программно (через DAO), сначала необходимо объявить объектную переменную и присвоить ей источник данных (Recordset):

Dim rst As DAO.Recordset     ‘ объявляем переменую
Set rst = CurrentDb.OpenRecordset(ПолеСоСписком.RowSource) ‘ ТекущаяБаза.ОткрытьИсточникСтрок(ПолеСоСписком.ИсточникСтолбцов)

а далее стандартная обработка Recordset

rst.AddNew     ‘ ДобавитьНовуюЗапись
rst(i) = NewData         ‘ НовыеДанные
rst.Update        ‘ скорректировать (обновить источник)
rst.Close          ‘ закрыть источник

    при работе с таблицей/запросом через DAO после выполнения действий со строками обязательно должно быть обновление источника rst.Update. Иначе компилятор тут же выдаст ошибку. И не забываем закрывать источник после работы  - освобождаем память. В принципе это не обязательно, при выходе из процедуры Access его все равно обнулит, но стоит выработать такую хорошую привычку - освобождать переменные в конце процедур.

    Вызывать функцию будем аналогично предыдущему примеру:

Private Sub Город_NotInList(NewData As String, Response As Integer)
Dim ctl As Control    ' Возвращает объект Control, указывающий на поле со списком
    Set ctl = Me!Город    ' назначаем переменной ctl текущий контрол (поле со списком)
' Приглашение подтвердить ввод нового значения
    Response = AppendLookupTable(ctl, ctl.Text)
    Me.Город.RowSource = Me.Город.RowSource     ' обновление списка (ведь там появился новый элемент)
End Sub

    Полный текст функции приведен в Пример1. Вариант3.

Формы - справочники.

    Теперь займемся наконец формами. Начнем с простого: создадим табличную форму - справочник. На событие «Открытие» формы вешаем процедуру:

Private Sub Form_Open(Cancel As Integer)
    Form.Caption = Me.Form.Name     ' присваиваем названию формы ее имя в базе
    DoCmd.MoveSize , , 5000, 3000   ' задаем размеры формы (ширина, высота)
    DoCmd.GoToRecord , , acNewRec   ' устанавливаем фокус на последнюю запись
End Sub

    Мы получили простейшую форму справочник. Осталось придумать, как же ее вызывать? Обычно применяют два способа:

  1. Раз справочник  - источник поля со списком, то почему бы дважды не щелкнуть по соответствующему списку для его открытия? А чтобы это как то узаконить, покрасим список в синий (можно, разумеется, и в любой другой) цвет и объявим в справке к программе, что при двойном щелчке по полю синего цвета открывается подобающая ему справочная таблица. Создаем процедуру открытия табличной формы:

Private Sub idРегион_DblClick(Cancel As Integer)
    DoCmd.OpenForm "Справочник регионы", acFormDS, , , , acWindowNormal
End Sub

    acFormDS - указание на то, что форма открывается в режиме таблицы
    acWindowNormal - указываем тип границы (вид формы) - обычная Windows («Нормальная» в конструкторе форм)

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

Private Sub Form_Close()
    If IsLoaded("Пример1") Then Forms!Пример1.idРегион.Requery          ' обновляем поле со списком idРегион на форме Пример1
End Sub

    IsLoaded - эта функция проверки, открыта ли форма "Пример1". Взята из базы «Боррей».

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

    Для организации подобного интерфейса нам понадобится служебная таблица «ФормыПараметры» и функция fOpenForm. В этом примере для разнообразия применим другой вид формы.

    Справочник у нас будет состоять из двух форм: простая форма будет служить контейнером для табличной. Поле серого цвета - поле фильтра. Начните вводить в него первые буквы искомого обозначения - и содержимое таблицы станет динамически фильтроваться (по первым буквам). Фильтрация происходит при помощи функции «fFilForm».

    А теперь самое интересное: я сделал только одну подобную форму справочник (основная форма «Справочник», починенная табличная «SubFrm»),  а в списке их у меня две: Страны, Регионы. И в базе вы не найдете форм «Справочник страны», «Справочник регионы». Откуда же они берутся? Все очень просто. Рассмотрим функцию «fOpenForm».

Function fOpenForm(КодФормы As String) As Boolean
On Error GoTo Err_
    strFormName = DLookup("ИмяФормы", "ФормыПараметры", КодФормы)
    strTextFormName = DLookup("ОбозначениеФормы", "ФормыПараметры", КодФормы)
    strTableName = DLookup("Таблица", "ФормыПараметры", КодФормы)
    DoCmd.OpenForm strFormName
    fOpenForm = True
Exit_:
    Exit Function
Err_:
    MsgBox Err.Description
    Err.Clear
    fOpenForm = False
    Resume Exit_
End Function

    Здесь мы видим процедуру присвоения значений трем переменным: strFormName, strTextFormName, strTableName. А теперь посмотрим на самый верх модуля «Module1». Там мы увидим

Public strFormName As String
Public strTextFormName As String
Public strTableName As String

    Здесь мы подошли к такому важному понятию, как область видимости переменных. Раз эти три переменных объявлены в разделе General общего модуля с ключевым словом Public, то они становятся видимыми для всех модулей приложения. Например, их "увидят" процедуры модуля формы «Справочник» для того чтобы присвоить форме соответсвующие параметры. Рассмотрим их.

    В таблице «ФормыПараметры» есть три поля: ИмяФормы (имя формы в приложении), ОбозначениеФормы (текстовое обозначение формы, или просто заголовок формы), Таблица (источник данных формы - имя таблицы). В функции «fOpenForm» происходит присвоение этим переменным значений при помощи

DLookup("ИмяПоляТаблицы/запроса", "ИмяТаблицы/запроса", "Условие отбора")

    как видно, значения берутся из полей служебной таблицы «ФормыПараметры». А затем команда на открытие формы DoCmd.OpenForm strFormName

    Теперь заглянем в модуль формы «Справочник». Рассмотрим процедуру, происходящую при открытии формы:

Private Sub Form_Open(Cancel As Integer)
    Form.Caption = strTextFormName
    Set idField = Me.П1
    strSql = "SELECT [" & strTableName & "].id, [" & strTableName & "].Обозначение FROM [" & strTableName & "]"
    strSql1 = " ORDER BY [" & strTableName & "].Обозначение"
    Subfrm.Form.RecordSource = strSql & strSql1
End Sub

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

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

    А теперь, попробуйте сами: "создайте" справочник «Города», заполнив соответствующими данными таблицу «ФормыПараметры».

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


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=9482