Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
3 Практический раздел.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
5.18 Mб
Скачать

Фильтрация

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

ПРИМЕЧАНИЕ

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

В качестве выражения, определяющего фильтр, используется строковое значение, составленное по определенным правилам. В состав фильтра могут входить такие элементы, как имена полей таблиц, литералы, скобки, операции сравнения, а так же арифметические и логические операции. Под литералом здесь понимается заданное явно значение - число, строка или символ. Из арифметических операций доступны такие, как сложение, вычитание, умножение и деление. В качестве логических операций можно использовать AND, OR и NOT. Ну а скобки используются, как обычно, для изменения порядка выполнения операций.

Для примера рассмотрим несколько вариантов фильтров:

BILL_SUMM > 150 BILL_CUST > 2 AND BILL_CUST < 5

В первом случае будут отобраны только те ряды, у которых в поле BILL_SUMM значение превышает 150, а во втором - ряды, поле BILL_CUST которых имеет значения больше 2 и меньше 5. Если в выражении фильтра используются строковые или символьные литералы, то они должны быть заключены в одинарные кавычки:

CUST_NAME = 'OOO "Alpha"'

Следует отметить, что когда фильтр задается не в инспекторе объектов, а программно, то следует использовать функцию QuotedStr на тот случай, если в строке окажутся символы одинарной кавычки:

Table1.Filter:='CUST_NAME = ' + QuotedStr(str);

Если же сам фильтр вводится в код программы как литерал, то можно заранее продублировать кавычки:

Table1.Filter:='CUST_NAME = ''OOO "Gamma"'';

Теперь создадим небольшое приложение, которое будет осуществлять фильтрацию записей в наборе данных. В качестве набора вновь используем таблицу (Table), так же нам понадобятся компоненты DBGrid и DataSource. Для управления фильтром поместим на форму компонент-редактор (Edit) и 2 кнопки (Button). Первая кнопка, назовем ее "Применить" будет включать фильтрацию путем присвоения значения, определенного в редакторе, свойству Filter таблицы и назначения значения истины свойству Filtered:

Table1.Filter:=Edit1.Text; Table1.Filtered:=true;

Вторая же кнопка - "Сброс" - будет просто отключать фильтрацию:

Table1.Filtered:=false;

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

Исходный код примера находится в каталоге Demo\Part4\Filter.

Еще одним свойством набора данных, имеющим отношение к фильтрации, является FilterOptions. Оно представляет собой набор из 2 флагов - foCaseInsensitive и foNoPartialCompare. Первый из них, будучи установленным, делает фильтрацию в строках регистронезависимой. Второй же заставит интерпретировать знак * (звездочку) как символ, в противном случае звездочка будет выполнять роль шаблона подстановки. Например, можно определить фильтр таким образом:

CUST_NAME = 'OOO *'

В том случае, если флаг foNoPartialCompare выключен, то будут отобраны все записи, начинающиеся с "ООО ". Если же этот флаг включен, то подойдет только запись, имеющая именно такое значение, т.е. "ООО *".

Поиск

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

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

Функция Locate производит поиск записи с удовлетворяющими условия поиска значениями полей. Если такая запись будет найдена, то курсор будет переведен на нее, а функция возвратит истину. Если же совпадений не найдется, то функция возвратит ложь. Определена эта функция следующим образом:

function Locate(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions): Boolean;

Здесь KeyFields определяет поля, по которым производится поиск, KeyValues - выражение для поиска, а Options задает такие параметры, как распознавание регистра в строках и возможность совпадения по части слова.

Для примера создадим приложение, которое сможет осуществлять поиск по названиям клиентов в нашей таблице Customers. Как обычно, понадобятся связка из компонентов Table, DataSource и DBGrid. Кроме них, задействуем однострочный редактор, кнопку и 2 переключателя типа CheckBox. Первый переключатель подпишем как "Без учета регистра", а второй - "Совпадение по части". Теперь остается написать код для процедуры обработки нажатия на кнопку, подобно тому, что приведен в листинге 19.3.

Листинг 19.3. Поиск с опциями

procedure TForm1.Button1Click(Sender: TObject);

var lo: TLocateOptions;

begin

lo:=[];

if CheckBox1.Checked then

lo:=lo+[loCaseInsensitive];

if CheckBox2.Checked then

lo:=lo+[loPartialKey];

Table1.Locate('CUST_NAME',Edit1.Text,lo);

end;

Данный пример иллюстрирует типичное применение поиска по одному полю (см. также пример в Demo\Part4\Search). В том же случае, если поиск необходимо провести по нескольким полям, то сами поля перечисляют через точку с запятой для параметра KeyFields и определяют массив значений для KeyValues:

Table1.Locate('CUST_NAME;CUST_ID',VarArrayOf(['OOO "Beta"',2]),lo);

Здесь производится поиск по полям CUST_NAME и CUST_ID, при этом совпавшими будут считаться записи, у которых в поле CUST_NAME будет значение "OOO "Beta"", а в поле CUST_ID - число 2. Что касается функции VarArrayOf, то она используется для одновременного создания и заполнения массива типа Variant.

Второй метод нахождения записей - Lookup - предназначен для нахождения искомого в источнике данных и возвращения нужных данных. Объявлена она следующим образом:

function Lookup(const KeyFields: string; const KeyValues: Variant; const ResultFields: string): Variant;

Первые 2 аргумента аналогичны тем, что имеются в функции Locate, а 3-й используется для того, чтобы определить поля, значения которых необходимо получить. Сами значения возвращаются либо в виде значения какого-либо простого типа, либо в виде массива, если для возврата запрашивается более одного поля.

Помимо того, что функция Lookup не перемещает курсор на найденное поле, она всегда работает в режиме "строгого" поиска, т.е. при отсутствии опций, понимается, что регистр надо различать, а частичное совпадение недопустимо.

Функции Locate и Lookup хороши тем, что могут использоваться для поиска по любым полям набора данных. Если же поиск требуется осуществлять по индексированным полям, то выбор методов существенно расширяется. В частности, для поиска одной записи можно использовать методы GotoKey и FindKey, производящие поиск по точному соответствию. А методы GotoNearest и FindNearest производят поиск по частичному соответствию. При этом перед вызовом методов GotoKey и GotoNearest необходимо вызывать метод EditKey или SetKey, чтобы перевести компонент Table в режим редактирования ключа поиска:

Table1.EditKey;

Table1.FieldByName('CUST_NAME').AsString := Edit1.Text;

if not Table1.GotoKey then ShowMessage('Совпадения не найдено!');

Здесь подразумевается, что поле CUST_NAME является индексированным.

Еще одна группа методов, работающих с индексированными полями, позволяет работать с диапазоном записей. К ним относятся: SetRangeStart, SetRangeEnd, EditRangeStart, EditRangeEnd, ApplyRange и CancelRange. Для использования поиска диапазона записей необходимо установить начало и конец диапазона вызовом функций SetRangeStart и SetRangeEnd, или EditRangeStart и EditRangeEnd, указывая при этом граничные значения полей. Затем, вызвав метод ApplyRange, указанный диапазон применяется к набору данных:

with Table1 do

begin

SetRangeStart; //включаем режим установки начала диапазона

FieldByName('CUST_ID').AsString:=Edit1.Text; //определяем начало диапазона

SetRangeEnd; //включаем режим установки конца диапазона

FieldByName('CUST_ID').AsString:=Edit2.Text; //определяем конец диапазона

ApplyRange; //Применяем диапазон end;

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