Filtering Datasets
( A topic for discussion )
Filtering a dataset is accessing just a subset of its rows when a
filter criteria is met.
There are two filtering methods:
Both filters can be applied dynamically or at design-time and both require the
Filtered property to be set for the filters to be activated. The
OnFilterRecord event handler is more powerful than the other, because we can code
in it almost any kind of complicated conditions. However since the filter condition is tested against each
of row in a dataset, this makes it inefficient way to filter huge data and other
more efficient methods may be used like sql or ranges.
Using the Filter property
The Filter property is merely a string that defines the value of condition to be
applied. The value of the filter property is set and reset by another property,
Filtered. After you specify a value for Filter, to apply the filter to the
dataset, set the Filtered property to True.
For example,
Dataset1.Filtered := False; // filtering is off
Dataset1.Filter := 'State = ' + QuotedStr(Edit1.Text);
Dataset1.Filtered := True; // now filtering is on
Using the OnFilterRecord event handler
The boolean parameter "Accept " of the OnFilterRecord event handler determines
the accepted records, when it is true, the tested record will be included in
the filtered subset.
For example,
procedure TForm1.Table1FilterRecord(DataSet: TDataSet; var Accept: Boolean);
begin
Accept := Pos('Blue', DataSet['Company']) <> 0;
end;
You can write as many OnFilterRecord event handlers as you need for a specific
dataset.
For example,
procedure TForm1.SomeFilter(DataSet: TDataSet; var Accept: Boolean);
begin
Accept := DataSet ['Company'] > 'I';
end;
procedure TForm1.OtherFilter(DataSet: TDataSet; var Accept: Boolean);
begin
Accept := DataSet ['Company'] > 'F';
end;
then you can call,
Table1.OnFilterRecord := SomeFilter;
or
Table1.OnFilterRecord := OtherFilter;
but the handlers will work independently, that
is to say if we write the following code:
Table1.Filtered:= True;
Table1.OnFilterRecord := SomeFilter; // any company name that is >
'I'
Table1.OnFilterRecord := OtherFilter; // any company name that is >
'F'
then the second handler "OtherFilter" will
produce a filtered subset of all the company names that are greater than 'F', as
if the first handler "SomeFilter" is set to nil, that is to say that the above
code is somehow equivalent to,
Table1.Filtered:= True;
Table1.OnFilterRecord := SomeFilter; // any company name that is >
'I'
Table1.OnFilterRecord := nil;
Table1.OnFilterRecord := OtherFilter; // any company name that is >
'F'
On the other hand, consider the following statements:
Table1.Filtered:= True;
Table1.OnFilterRecord := SomeFilter; // any company name that is >
'I'
Table1.Filter := 'Company' + '>'+ QuotedStr('F'); //
Here the filter property actually filters the
subset that was already filtered by the SomeFilter handler.
But surprisingly, the following code,
Table1.Filtered:= True;
Table1.Filter := 'Company' + '>'+ QuotedStr('I'); //
Table1.Filter := 'Company' + '>'+ QuotedStr('F'); //
also has a similar scenario as applying a two
OnFilterRecord event handlers.
to be continued .. |