|
10.01.2013, 18:24 | #1 |
Участник
|
Фильтрация данных в форме по «виртуальным» полям с использованием методов OnFindRecord и OnNextRecord формы
Цель данной публикации – описать возможность фильтрации данных в форме по «виртуальным» полям с использованием методов OnFindRecord и OnNextRecord формы. Данный вопрос частично освещён на многих Интернет-ресурсах, но полного разложения «по полочкам» с конкретными примерами найти практически нереально. В рамках подготовки публикации были собраны почти все «шишки» данного метода фильтрации. Если внимательные читатели при анализе решения обнаружат неточность – просим сообщать незамедлительно. Используемые термины: • «виртуальное» поле формы – некое поле записи, отображаемое на форме. Не связано ни с одним полем таблицы. Значение поля вычисляется в триггере OnAfterGetRecord формы. История вопроса Заказчик имел ряд форм, в которых использовались «виртуальные» поля. Необходимо было сделать механизм отбора записей. При этом пользователь должен был иметь возможность отобрать записи по одному из следующих алгоритмов – все записи, только записи с определённым статусом, только записи без определённого статуса. Варианты решения • Использование механизма маркировки записей. Недостаток - много времени уходит на перебор записей и проставление маркировок, затраты времени. • Подмена записей в форме данными из виртуальной таблицы с использованием методов OnFindRecord и OnNextRecord формы. Недостаток - необходимость управлять временной таблицей при любом изменении записей, затраты времени. • Игнорирование записей, не удовлетворяющих условию отбора, с использованием методов OnFindRecord и OnNextRecord формы. Недостаток – работает немного дольше, чем обычная форма. Как догадался читатель, был выбран последний вариант. Реализация На форме были добавлены 4 функции (см. приложенные файлы с проектом): 1. ShowThisRecord Код: IF g_AdditionsFilter=g_AdditionsFilter::All THEN EXIT(TRUE); CASE g_AdditionsFilter OF g_AdditionsFilter::WithAdditions: BEGIN IF CheckAdditionsExists(p_FilterExampleTable1)=FALSE THEN EXIT(FALSE) ELSE EXIT(TRUE); END; g_AdditionsFilter::WithoutAdditions: BEGIN IF CheckAdditionsExists(p_FilterExampleTable1)=TRUE THEN EXIT(FALSE) ELSE EXIT(TRUE); END; END; Код: RecRef2.COPY(Rec); IF Which = '' THEN Which := '='; FOR i := 1 TO STRLEN(Which) DO CASE Which[i] OF '-': BEGIN IF Rec.FIND('-') THEN REPEAT IF ShowThisRecord(Rec) THEN EXIT(TRUE); UNTIL Rec.NEXT = 0; END; '+': BEGIN IF Rec.FIND('+') THEN REPEAT IF ShowThisRecord(Rec) THEN EXIT(TRUE); UNTIL Rec.NEXT(-1) = 0; END; '=': BEGIN IF Rec.FIND THEN IF ShowThisRecord(Rec) THEN EXIT(TRUE); END; '>': BEGIN IF NEXTPosition(Rec, 1) <> 0 THEN EXIT(TRUE); END; '<': BEGIN IF NEXTPosition(Rec, -1) <> 0 THEN EXIT(TRUE); END; END; Rec.COPY(RecRef2); EXIT(FALSE); Код: IF Steps = 0 THEN EXIT; IF Steps > 0 THEN Direction := 1 ELSE Direction := -1; RecRef2.COPY(RecRef); RecRef3.COPY(RecRef); REPEAT IF RecRef.NEXT(Direction) = 0 THEN BEGIN RecRef.COPY(RecRef3); EXIT; END; IF ShowThisRecord(RecRef) THEN BEGIN RecRef3.COPY(RecRef); StepsCount += Direction; END; UNTIL ABS(StepsCount) >= ABS(Steps); IF StepsCount = 0 THEN RecRef.COPY(RecRef2) ELSE RecRef.COPY(RecRef3); Код: l_FilterExampleTable2.RESET; l_FilterExampleTable2.SETFILTER(l_FilterExampleTable2."Example Code",p_ExampleFilterTable1."No."); EXIT(l_FilterExampleTable2.FIND('-')); 1. OnFindRecord Код: Found := FINDPosition(Which); EXIT(Found); Код: RecRes.COPY(Rec); NextStep := NEXTPosition(RecRes,Steps); IF NextStep <> 0 THEN Rec.COPY(RecRes); EXIT(NextStep); Полный код решения на простом примере приложен в файлах find-next.fob, find-next.txt
__________________
Незнание закона не освобождает от ответственности... От ответственности освобождает знание закона! Компания НЭТИ - http://i-neti.ru/ |
|