Tips Forum Logo
Downloads Home PageSpacerVisit Microsoft DownlodsMAUG Home PageMAUG Russian Home Page

Что такое Lookup или эффективная работа с Microsoft Access могла быть эффективней, если не…

Грибанов Сергей Юрьевич
E-Mail
prbasic@lcpi.lipetsk.ru

 

Вначале небольшая выдержка из справочной системы MSAccess по свойству формы .Filter

***********************************************************************************************

Свойство «Фильтр» (Filter)

Свойство Фильтр (Filter) определяет подмножество записей, выводящихся после применения фильтра к форме, запросу или таблице.

Значения

Значение свойства Фильтр (Filter) определяется строковым выражением, содержащим предложение WHERE без ключевого слова WHERE. Например, следующие инструкции Visual Basic определят фильтр, отбирающий клиентов из России:

Me.Filter = "Страна = 'Россия'"
Me.FilterOn = True

***********************************************************************************************

Рассмотрим частный случай для форм, т.к. на практике пользователи чаще работают именно с формами.

Из написанного: "Значение свойства Фильтр (Filter) определяется строковым выражением, содержащим предложение WHERE без ключевого слова WHERE " ясно что строковое выражение содержит СТАНДАРТНУЮ строчку SQL, только без ключевого слова WHERE, следовательно, эта строчка должна обрабатываться стандартными функциями Access ApplyFilter, Dlookup и другими, которые используют SQL, а также в объектах Recordset и им подобных, это утверждение почти верно, но на практике, оказалось, по другому, хочу отметить также, что на длину строки SQL в свойстве формы .Filter наложено ограничение на размер в 2048 байт.

Зачем вообще нужно свойство .Filter в формах? Где его можно использовать?

Не знаю, для чего конкретно хотела использовать его Microsoft, хороших примеров на данную тему я так и не встретил, мне это свойство подходило для конкретной задачи поставленной заказчиком. Задача заключалась в следующем:

Имелась форма с записями, пользователь должен был находить какие-то данные и на их основе создавать несколько табличных форм, содержащих найденные записи и строить несколько временных отчетов подряд для сверки каких-то своих данных, полей форма содержала много и создать фиксированное количество форм и отчетов для всех условий было довольно затруднительно, проще было создать одну форму на которую накладывались условия, в зависимости от данных найденных в основной форме, для этих целей я и выбрал свойство .Filter формы, казалось бы, все замечательно, применил пользователь фильтр к форме, открыл табличную форму, где на данные накладывалось условие по WHERE .Filter, свернул ее, нашел новые данные, открыл новую форму и т.д. и действительно все работает, когда фильтр применяется из собственноручно написанного кода, например DoCmd.AppleyFilter ,"[Id]=100". В этом случае строчка в .Filter будет содержать "[Id]=100", проблемы возникли, когда пользователь стал применять команды "Исключить выделенное" и "Фильтр по выделенному", они показали некорректную работу с присоединенными значениями в списках формы и как выяснилось в дальнейшем некорректную работу почти во всем.

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

Имеется небольшая БД, состоящая из нескольких таблиц (в данном случае используются две), и между двумя из них установлена связь по конкретному полю, очень распространенный прием, (см рисунок)BugLookup1.gif (4325 bytes)

Поле [CodeTypeID] в основной таблице (Data)Склад содержит в данном примере коды типов комплектующих, которые связанны с соответствующей списочной таблицей (см. рисунок) в отношении многие к одному. Повторяюсь, очень простой и очень распространенный вариант построения структуры БД, на основе этих таблиц создана форма (см. рисунок), которая содержит поле, и два раскрывающихся списка, один из списков (Тип) содержит два столбца, первый столбец включает код типа и имеет нулевую ширину, он же связан с основным полем [CodeTypeID] в основной таблице (Data)Склад, второй столбец собственно отображает название типа комплектующих, тоже достаточно распространенный вариант. Теперь запустите данный пример и откройте форму "BugLookup", поместите курсор на поле "Склад" и нажмите в Меню кнопку "Фильтр по выделенному", после этого нажмите кнопку "Показать Me.Filter" на форме, вы увидите, что-то вроде (([(Data)Склад].Склад="Петров")), проанализируйте увиденное, что ж вполне приемлемая строчка SQL получается, а теперь нажимайте на "Фильтр по выделенному" еще раз и нажмите кнопку "Показать Me.Filter", что же мы видим? Строчка стала иметь следующий вид ((([(Data)Склад].Склад="Петров"))) AND (([(Data)Склад].Склад="Петров")), часть конструкции постоянно повторяется не неся уже никакой смысловой информации, при многократных нажатиях строчка будет лишь увеличиваться пока не исчерпается лимит на размер строки в Me.Filter - 2048 байт. Исходя из этого, сформулируем:

 

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

Рассмотрим теперь пример для команды "Исключить выделенное", предварительно очистите свойство .Filter формы (Кнопка "Удалить Me.Filter"), поместите курсор на поле "Склад" и нажмите в меню кнопку "Исключить выделенное", нажмите кнопку "Показать Me.Filter", строка .Filter будет иметь вид ((Not[(Data) Склад].Склад="Петров")), здесь все нормально и с точки зрения разбора полученной строки SQL, проблем не будет, но если вы еще раз нажмете кнопку "Исключить выделенное", случится следующее: либо форма перейдет на новую запись, либо, если у вас стоит запрет на ввод новых записей в форме, все элементы в области данных исчезнут и вам придется нажать кнопку "Удалить фильтр" для отображенья всех записей, что не всегда удобно, а в некоторых случаях может привести к ошибке. Исходя из этого, сформулируем:

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

Рассмотрим пример для поля "Тип", оно отличается от других наличием присоединенного столбца, очистите свойство .Filter формы (Кнопка "Удалить Me.Filter"), поместимте на данное поле курсор и нажмите кнопку "Фильтр по выделенному", нажмите кнопку "Показать Me.Filter", строка .Filter будет иметь вид ((Lookup_ctrlТип.Тип="RES"))., что уже неприемлемо, мало того, что появился неизвестный префикс Lookup, так и данные берутся не из поля, а из элемента управления ctrlТип. Эта строчка уже не обрабатывается стандартными функциями (Dcount и т.д.). Исходя из этого, сформулируем:

3. При выборе команды "Фильтр по выделенному" и "Исключить выделенное" к полям, содержащих присоединенный столбец, строчка SQL в свойстве формы Filter, примет необрабатываемый вид.

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

Для замены стандартных функций Access нам потребуется одна главная и несколько вспомогательных функций, они размещены в модуле acFormUtl в прилагаемой БД, это

1.FrmFilterSelection -основная функция для замены "Фильтр по выделенному" и "Исключит выделенное"

2.FrmSort -функция для замены сортировок от А до Я и от Я до А

3.FrmShowAllRecords -функция замены "Удалить фильтр/Показать все записи"

4.MeBuildCriteria -функция замены BuildCriteria из за некорректной работы с символами шаблона ,а также функция cmdBarButtonED в модуле формы для задания свойств .Enabled в меню для кнопок отвечающих за фильтрацию и сортировку. Также необходимо включить следующий код на событие формы Open:

Private Sub Form_Open(Cancel As Integer)

Me.FilterOn = False 'Запрещаем применение сохраненных фильтров
Me.OrderByOn = False 'Запрещаем применение сохраненной сортировки
Me.Filter = "" 'Обнуляем фильтр

End Sub

Функции 1,2,3 в форме должны всегда использоваться вместе, они пересекаются по свойству .Filter и не включения любой из них приведет к некорректной работе других. Эти функции рекомендуется использовать в меню, в последнем случае они обязательно должны быть объявлены как Function, а не Sub, что связанно с их вызовами Access из меню или панелей инструментов.

Подробно разбирать эти функции в данной статье я не буду, код достаточно прост.

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

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

----------

MAUG: Вместе с примером Вы также можете загрузить и полный текст статьи в формате Microsoft Word.

Интересно также почитать комментарии на статью, файл Comments.doc, вместе с примером



Microsoft Access Solutions

Written and designed by
Alex Dybenko
Send us your comments
Last Update: 2006-01-23
Copyright © 1998-2006 by MAUG