Справочники. Часть 4. Многоуровневые справочники.

Источник: Leadersoft

Многоуровневые справочники.

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

    В предыдущей главе предлагалось вместо создания множества однотипных справочников сделать один макет справочной формы и цеплять к нему источник данных при запуске. Но можно углубиться еще дальше. Воспользуемся идеей, которую предложил Валерий Крук - сделаем одну справочную таблицу и будем хранить в ней данные всех справочников. Для этого потребуется еще одно поле - идентификатор «справочной таблицы», чтобы определить, к какому справочнику относится данная запись. А для реализации двухуровнего справочника создадим вторую таблицу, в которой будут храниться связанные с первой таблицей записи.

Имя таблицы

Имя поля

Тип поля

СПРАВОЧНИК

id

счетчик

Name

Текстовое

Type

Длинное целое

СПРАВОЧНИК Sub

id

счетчик

id1

Длинное целое

Name

Текстовое

    При установке связей между таблицами СПРАВОЧНИК и СПРАВОЧНИК Sub установим флажок «Каскадное удаление связанных записей» - это как раз тот случай, когда такая процедура будет полезной. Ведь при удалении записи из таблицы «СПРАВОЧНИК» связанные с ней данные становятся не нужными.

    Если Вы откроете схему данных, то увидите только две связанные между собой справочные таблицы. В предыдущем примере к основной таблице «Адресат» были привязаны все справочники, и я еще подробно рассказывал о связях, флажках… Дело в том, что при данной схеме организации справочной системы мы не сможем прицепить таблицу «СПРАВОЧНИК» к какому либо полю, ведь в ней теперь хранятся все справочные данные. Да в этом и нет надобности. Если учесть, что пользователь будет работать с базой исключительно через формы, то вероятность ввода в основную таблицу записей, которых нет в справочной, сводиться практически к нулю.

    Параметры справочников хранятся в служебной таблице tSystemFormPar. В поле Tabl указан идентификатор соответствующего справочника.
Рассмотрим отличия от предыдущего варианта.

    Все глобальные переменные и константы я  перенес в специальный модуль, который так и называется Constants. Хотя объявлять их можно в любом модуле, главное, чтобы они были в разделе General и начинались с ключевого слова Public, но лучше хранить их для наглядности в одном месте.

    В модуль SprawForm добавилась новая функция - fFilListBox. Она во многом похожа на fFilForm, но служит для фильтрации списка, поэтому в параметрах вместо frm As Form поставлено lst As ListBox. Кроме этого, в  обеих функциях изменена строка формирования фильтра:

strFiltr = " WHERE Left([" & strFieldName & "]," & Len(strFiltr) & ") = '" & strFiltr & "'" & " and СПРАВОЧНИК.Type = " & strTableName

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

RecordSource = strSql1 & strFiltr & " " & strSql2

то для списка нужно использовать свойство RowSource

RowSource = strSql & strFiltr & " " & strSql1

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

    В модуле формы «Справочник» добавилось условие отбора по полю Type таблицы СПРАВОЧНИК

Me.Subfrm.Form.RecordSource = strSql2 & " WHERE СПРАВОЧНИК.Type = " & strTableName & strSql3

и появилось новое - присвоение полю Type значения по умолчанию, равное текущему значению переменной strTableName

Me.Subfrm.Form!Type.DefaultValue = " & strTableName

    Ведь если этого не сделать, то запись в таблице СПРАВОЧНИК окажется не привязанной к текущему типу справочника.

    В модуле формы двухуровневого справочника «СправочникМ» видим, что формируются две пары строк - источников данных: strSql, strSql1 - для списка и strSql2, strSql3 - для табличной формы. Строки разбиты на пары потому, что между ними нужно будет вставлять условие отбора (WHERE…) Чтобы новое введенное значение в поле формы тут же отображалось в списке, служит процедура

Private Sub Fld_AfterUpdate()
    DoCmd.RunCommand acCmdSaveRecord
    Me.ListB.RowSource = strSql & " WHERE СПРАВОЧНИК.Type = " & strTableName & strSql1
End Sub

А для навигации по форме (поиску нужной записи) используем

Private Sub ListB_AfterUpdate()
Dim rs As Object
    Set rs = Me.Recordset.Clone
    rs.FindFirst "[id] = " & Str(Nz(Me![ListB], 0))
    If Not rs.EOF Then Me.Bookmark = rs.Bookmark
End Sub

    Чтобы исключить возможность ввода в табличную форму (источник - СПРАВОЧНИК Sub) записей, не связанных с основной формой (источник - СПРАВОЧНИК) служит процедура, которая выводит соответствующее сообщение при подобной попытке и блокирует ее:

Private Sub Subfrm_Enter()
    If flgDeleteRecord = False Then
        If IsNull([id]) Then
            MsgBox "Сначала нужно завести основные данные!", vbCritical, NomWers
            Fld.SetFocus
        End If
    End If
End Sub

    Раз на форме появилось второе поле фильтра, появилась соответствующая процедура фильтрации по этому полю

Private Sub П2_Change()
    strFiltr = Me.П2.Text
    Set idField = Me.П2
    Call fFilForm(strFiltr, strSql2, strSql3, Me.Subfrm.Form, "Name")
End Sub

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

А теперь можете поэкспериментировать, создавая разного вида справочники  - простые и двухуровневые.


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