Фильтрация набора данных в Delphi с помощью свойства Filter

Фильтрация набора данных в Delphi с помощью свойства Filter

Фильтрация набора данных в Delphi с помощью свойства Filter — одна из интереснейших тем. Свойство Filter является очень гибким инструментом. Сегодня я попробую представить для вас самые интересные возможности этого свойства. Многие из них показаны на различных блогах, но есть и такие, которые на просторах интернета или в книгах не найти. Я определил их опытным путем.

Я собираюсь применить данный фильтр на практике и это будет интересно. Но давайте начнем пожалуй с небольшой теории. Что такое свойство Filter набора данных простыми словами.

Общее понимание фильтрации через свойство Filter

Давайте представим с вами команду SELECT. Это сильная команда для осуществления выборок одной или нескольких объединенных таблиц базы данных. С помощью данной команды можно установить и условие выборки в предложении WHERE. И тогда мы получим не все записи таблицы, а лишь те, которые удовлетворяют условию WHERE.

Для чего же тогда необходимо свойство Filter и фильтрация через него? Все очень просто. Команда SELECT делает выборку лишь необходимых данных. То есть, в набор данных (рассмотрим на примере adoQuery и я думаю, что эта статья будет актуальна и для С#, а так же для VB .net) загружаются только записи, которые удовлетворяют условию, но не все записи набора данных.

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

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

Можно выполнять каждый раз команду SELECT, но если таблица большая, то каждый раз, когда вы отправляется на сервер эту команду, Вас будет сопровождать неприятная задержка, пока СУБД обработает записи и вернет результат. Поэтому для таких целей и удобно использовать свойство Filter набора данных. В этом случае вы примените фильтр к уже отобранным из таблицы записям и не ощутите задержку в выполнении фильтрации.

Ну что, а теперь обратимся к примеру.

delphi filter
Пример фильтрации данных с помощью свойства Filter

Давайте посмотрим на это окно. Это реальная задача, которую я сейчас выполняю в своей организации. Ну точнее говоря — это лишь одно окно программы, но именно оно нам сейчас и будет нужно для понимания работы.

Кстати говоря, внешний вид этого окна полностью выполнен в Delphi. И выполнено это даже не на FMX-библиотеке, а на обычной классической библиотеке VCL, что является прямым аналогом Windows Forms в Visual Studio. И если, кто то еще сомневается в Delphi или считает, что среда или язык мертвы, то это абсолютные глупости.

Многие пишут, что: «Если вы хотите по быстрому накидать компонентов на форму и слепить не сложное приложение, то выбор в пользу Delphi, если серьезное приложение, то Java или Другой язык». Честно сказать, всегда хочется увидеть этого человека и «пару раз справа...», чтобы ум на место встал.

Запомните раз и навсегда: Delphi создавался для разработки сложных приложений и остается по сей день таким же. Так, ну ладно, отступили от темы. Как создавать красивый внешний вид приложений (сейчас модно называть «Кастомный») в библиотеке VCL, я опишу в следующей статье, потому что эта тема связана с поддержкой стилей. Там я прямо покажу, как создать конкретно стиль. Ну а здесь, как говорится в Web-тематике — будем рассматривать Backend-разработку, если так можно выразиться к приложению под WIndows. Но я думаю, что наверное можно. Вполне.

Практические приемы работы со свойством Filter

Посмотрим на окно «Соответствие КВР и КОСГУ». Смысл данного окна в том, что верхняя и средняя таблицы являются справочниками, из которых информацию попадает в нижнюю таблицу. То есть, происходит связывание КВР и КОСГУ в разных комбинациях (в которых это необходимо). Связь между таблицами КВР и КОСГУ в базе данных в этом случае реализована как много-ко-многим. О том, как организовать данную связь смотрите информацию в статье «Виды связей между таблицами».

Справочники КВР и КОСГУ могут быть довольно большими. Поэтому целесообразно для этого использовать поиск. Как поступаю я в этом случае? Я размещаю под столбцами таблиц (объектов TDBGrid) поля (TEdit), которые являются, как я их называю" быстрым поиском, то есть поиск сразу осуществляется при вводе символов с клавиатуры в конкретном TEdit.

Естественно, что этот поиск осуществляется по столбцу, под которым расположен этот TEdit. Как я уже писал выше, для этого есть два пути: можно воспользоваться командой SELECT, а можно использовать Delphi filter.

В данном случае я предпочитаю использовать именно Delphi filter. И причина этому предельно проста. Мне кажется, что каждый раз, когда пользователь нажимает кнопку на клавиатуре и вводит новый символ очень неудобно вызывать SELECT. Ведь эта команда при каждой выборке будет перестраивать полностью набор данных — снова и снова.

Здесь гораздо эффективнее извлечь при открытии формы справочник полностью той же командой SELECT, а потом использовать к этой выборке (к сформированному набору данных) Delphi filter.

Filter — это свойство набора данных, которое имеет текстовый тип. И в интернете очень много статей о том, как использовать данное свойство, но все примеры довольно простые. Я же приведу здесь примеры более интересные, которые я собственноручно протестировал во время разработки своих программ. Но начнем все же с простых вещей, чтобы идти по порядку.

Итак, чтобы найти нам нужный КВР по его названию необходимо воспользоваться таким кодом:

adoKVR.Filtered:=false;
adoKVR.Filter:='Название '+ ' LIKE ' + #39 + '%' + TEdit(Sender).Text + '%' + #39;
adoKVR.Filtered:=true;

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

При этом удобно вместо свойства Name у объекта TEdit использовать TEdit (Sender). Это более универсально и грамотно с точки зрения построения кода, поскольку в этом случае вы никогда не ошибетесь с именем объекта TEdit. То есть, по простому — это означает текущий объект.

Оператор #39 является кавычками. Далее идет знак %, что означает также, что частичное совпадение может быть с любой позиции искомой строки. То есть, это как поиск в операционной системе. Только в операционной системе для этого используется *.

Вообще эту строку можно написать и вот так:

adoKVR.Filter:='Название '+ ' LIKE ' + '%' + TEdit(Sender).Text + '%';

И это тоже отлично работает.

Результат будет таким:

delphi filter
delphi filter

Мы могли бы ввести слово «оплата труда» и получили бы тот же самый результат. Ну что ж, отлично, двигаемся далее. Давайте теперь посмотрим на полную процедуру (метод/код). Вообще мы должны эту процедуру куда то поместить. В данном случае нам удобно поместить код в событие под названием Change. Это событие возникает, когда у элемента управления меняется значение.

procedure TfrmKVRandKOSGU.txtCaptionKOSGUChange(Sender: TObject);
begin
     if TEdit(Sender).Text<>'' then
     begin
        txtArticleKOSGU.Text:='';
        txtStatusKOSGU.Text:='';
        adoKOSGU.Filtered:=false;
        adoKOSGU.Filter:='Название '+ ' LIKE ' + #39 + '%' + TEdit(Sender).Text + '%' + #39;
        adoKOSGU.Filtered:=true;
     end else
     begin
        adoKOSGU.Filtered:=false;
     end;
end;

Давайте рассмотрим этот код. Мы видим процедуру (метод), который обрабатывает событие Change. Внутри метода код начинается со строк:

if TEdit(Sender).Text<>'' then

что можно прочитать так: если свойство Text текущего объекта TEdit не пустое, то... далее идет:

txtArticleKOSGU.Text:='';
txtStatusKOSGU.Text:='';

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

Далее, собственно идет уже рассмотренная ранее строка построения фильтра. А чуть ниже строка, удовлетворяющая условию, если Text пустое, то фильтр в наборе данных отключается.

Давайте теперь посмотрим на то, как можно строить фильтры с датами, числами, фильтры с двойным условием и т.п.

Delphi filter по полю типа Date:

var
     sDate: string;
begin
     sDate:=DateToStr(DateTimePicker1.Date);
     adoQuery1.Filtered:=false;
     adoQuery1.Filter:='Дата_занятия '+ ' = ' + QuotedStr(sDate);
     adoQuery1.Filtered:=true;
end;

Здесь обязательно необходимо привести дату к строковому типу. Это мы делаем с помощью функции DateToStr. Функция QuotedStr обертывает строковую переменную sDate в одинарные кавычки. Можно также записать следующим образом:

adoQuery1.Filter:='Дата_занятия '+ ' = ' + '''sDate''';

либо так:

adoQuery1.Filter:='Дата_занятия =' + '''sDate''';

Это все небольшие вариации одного и того же. Давайте же теперь посмотрим на то, как сделать фильтр Delphi filter по диапазону дат:

var
   sDate1: string; //Начальная дата
   sDate2: string; //Конечная дата
begin
   sDate1:=trim(Edit1.Text);
   sDate2:=trim(Edit2.Text);
   ADOQuery1.Filtered:=false;
   ADOQuery1.Filter:='Дата_рождения>='+sDate1+' and '+'Дата_рождения<='+sDate2;
end;

Теперь давайте посмотрим как сделать фильтр данных Delphi по двум полям:

adoQuery1.Filter:='Номер_класса = '''+txtFindKl.Text+''''+' and '+'Название_литеры = '''+txtFindLitera.Text+'''';

А теперь по четырем полям:

adoQuery1.Filter := 'Номер_класса = '''+txtFindKl.Text+''''+' and '+'Название_литеры = '''+txtFindLitera.Text+''''+' and '+'Дата>='''+sDate1+''''+' and '+'Дата<='''+sDate2+'''';

То есть, Delphi filter как и условие в команде SELECT может быть составным с использованием такие уловных операторов как AND, OR, NOT и так далее.

Посмотрим, где еще может быть полезно свойство Filter. С помощью этого свойства можно организовать форму по типу Master-detail с двумя наборами данных. Соответственно, для этого в TDataSource родительского набора данных в событии OnDataChange , которое возникает при перемещении на другую запись нужно написать так:

procedure TfrmPhotoAlbom.dsAlbomDataChange(Sender: TObject; Field: TField);
begin
  adoPhoto.Filtered:=false;
  adoPhoto.Filter:='ID_фотоальбома '+ ' = ' + #39 + inttostr(adoAlbom.FieldByName('id_фотоальбома').asinteger) + #39;
  adoPhoto.Filtered:=true;
end;

В этом примере родительский набор данных — это adoAlbom (альбомы), а подчиненный — adoPhoto (фотографии). Соответственно, с adoAlbom связан компонент TDataSource по имени dsAlbom. И уже в событии OnDataChange этого объекта мы и размещаем вышепоказанный код.

При этом в свойстве Filter мы используем внешний ключ id_фотоальбома таблицы «Фотографии». Это же поле является первичным ключом таблицы «Альбомы». То есть, получается, что мы в фильтре оставляем все записи в набора фотографий, у которых значение поля id_фотоальбома равно значению поля id_фотоальбома в наборе альбомов.

Давайте теперь посмотрим на то, как с помощью Delphi filter можно отфильтровать все пустые значения по полю или, наоборот, исключить их.

Исключаем (прячем в наборе данных) все пустые значения по полю «ФИО»:

adoFIO.Filtered:=false;
  adoFIO.Filter:='ФИО'+' <> Null';
  adoFIO.Filtered:=true;

Теперь, наоборот, выводим только пустые значения по полю «ФИО»

adoFIO.Filtered:=false
  adoFIO.Filter:='ФИО'+' = Null';
  adoFIO.Filtered:=true;

Давайте теперь посмотрим, как можно сделать фильтрацию по числовому полю:

adoQuery1.Filtered:=false;
  adoQuery1.Filter:='ID_договора '+ ' = ' + #39 + txtFind2.Text + #39;
  adoQuery1.Filtered:=true;

Здесь нужно будет обратить на два момента: при фильтрации по числовому полю не должен быть использован оператор LIKE. Он работает только со строками; и второй момент — значение для числового поля в строке фильтра должно быть приведено к строковому типу String.

Ну вот мы и завершаем наш небольшой обзор по теме применения фильтрации набора данных в Delphi с помощью свойства Filter.

Понравилась статья? Поделиться с друзьями:
Блог Алексея Иванкова
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: