1

I'm using Delphi 10 with Firemonkey, i'm a bit new to it. I have a TStringGrid that i bound with LiveBindings to a access database. What I need is to filter this table or the TStringGrid with the text of a TEdit when I press a button or when any key is enter, and the show it in the results in the same TstringGrid. Just like a custom search/filter box.

I don't have any code of this yet. But i think it would be like a query.
procedure TForm3.Edit2Typing(Sender: TObject); begin adoquery1.Close; adoquery1.SQL.Text:='select * from instrutor where nome like " %' + edit2.text + '%"'; adoquery1.Open; end;
I've tried this but since I already have a livebinding with the adotable and the stringgrid, i don't the way i should link this Tedit

  • Please add the code you're tried to the q. Or are you saying you do not know where to begin? – MartynA Nov 14 '15 at 12:33
  • Like q query, sure. But the expression "filter", in a Delphi dataset context, usually means operating on (e.g. displaying) only a subset of records which have *already* been retrieved from the database into the Delphi app. So you need to decide whether you want a query or a filter and say. – MartynA Nov 14 '15 at 12:52
  • Ok, I should use the AdoTable.Filter propertie. Now I just have to bind it with the stringgrid? – Guilherme Raguzzoni Nov 14 '15 at 13:00

1 Answers1

3

The example below is a minimal application using live binding between a TAdoQuery and a TStringGrid. I've done it for convenience as a VCL application rather than an FMX one, but that doesn't make any difference to how to do filtering on a live-bound AdoQuery.

It uses 2 TEdits to specify the filter value to match and the name of the field to filter on (in practice it would be better to do something like populate a listbox with the available field names).

The main "work" is done in the UpdateFilter procedure.

The fact that it uses live binding doesn't make any difference to how to apply the filter to the dataset. However, live binding to a StringGrid is significantly slower than a traditional (VCL) TDBGrid. An important thing to avoid is the situation where the dataset has a large number of fields and there is one stringgrid column for each field because it can make the app very slow to respond to changes in the filter criteria. A way to mitigate the effect of this is simply to restrict the number of stringgrid columns to a much lower number, by setting the ColCount of the stringgrid to a suitably low value. An alternative is to define persistent fields for the dataset, but only create a few of them.

In the code below, I've used the OnChange events of the TEdits to update the FilterFieldName and FilterValue fields, but obviously you could have a separate button to click to call the UpdateFilter procedure.

Code:

TForm1 = class(TForm)
  ADOConnection1: TADOConnection;
  ADOQuery1: TADOQuery;
  StringGrid1: TStringGrid;
  BindingsList1: TBindingsList;
  DataSource1: TDataSource;
  LinkGridToDataSource1: TLinkGridToDataSource;
  BindSourceDB1: TBindSourceDB;
  edFilterFieldName: TEdit;
  edFilterValue: TEdit;
  procedure FormCreate(Sender: TObject);
  procedure edFilterFieldNameChange(Sender: TObject);
  procedure edFilterValueChange(Sender: TObject);
private
  FFilterFieldName : String;
  FFilterValue : String;
  procedure SetFilterFieldName(const Value: String);
  procedure SetFilterValue(const Value: String);
  procedure UpdateFilter;
public
  property FilterFieldName : String read FFilterFieldName write SetFilterFieldName;
  property FilterValue : String read FFilterValue write SetFilterValue;
end;

[...]

procedure TForm1.FormCreate(Sender: TObject);
begin
  FilterFieldName := edFilterFieldName.Text;
  FilterValue := edFilterValue.Text;
end;

procedure TForm1.edFilterFieldNameChange(Sender: TObject);
begin
  FilterFieldName := edFilterFieldName.Text;
end;

procedure TForm1.edFilterValueChange(Sender: TObject);
begin
  FilterValue := edFilterValue.Text;
end;

procedure TForm1.SetFilterFieldName(const Value: String);
begin
  if FilterFieldName <> Value then begin
    FFilterFieldName := Value;
    UpdateFilter;
  end;
end;

procedure TForm1.SetFilterValue(const Value: String);
begin
  if FilterValue <> Value then begin
    FFilterValue := Value;
    UpdateFilter;
  end;
end;

procedure TForm1.UpdateFilter;
var
  Expr : String;
begin
  AdoQuery1.Filtered := False;

  //  The next statement checks whether the FilterFieldName
  //  matches a field in the dataset and exits if not.  Since the
  //  FilterFieldName value comes from an edit box, it will be incomplete while the user is typing it in
  if AdoQuery1.FieldByName(FilterFieldName) = Nil then
    exit;
  if FilterValue <> '' then begin
    Expr := FilterFieldName + ' like ' + QuotedStr('%' + FilterValue + '%');
    AdoQuery1.Filter := Expr;
    AdoQuery1.Filtered := True;
  end;
end;
MartynA
  • 30,454
  • 4
  • 32
  • 73
  • Ok I used your example and using the filter propertie in AdoQuery this works fine. I just had to change the 'Like' to '=' since i'm using access and apparently it doesn't accept 'like'. And i have to enter the the full name to it appear. How can I make it appear when I enter part of the name? Like 'te' instead of 'test' or something like this. This is the sentence: `adoquery1.Filter:=('Name='+ QuotedStr(Edit2.Text));`. – Guilherme Raguzzoni Nov 16 '15 at 13:00
  • Actually, I just tested my code against an MS Access database using the Microsoft.Jet.OLEDB.4.0 driver in the AdoConnection string and it works fine, including the use of 'like' against a column defined as Char(40). What Access driver are you using? – MartynA Nov 16 '15 at 13:54
  • I'm using the same. I tried to input the filter syntax like yours and others similiar to this, but none worked. For me it's fine working this way, but making it more "dynamic" would be more user-friendly. I'll mark your reply as answer but I would be grateful if you help me find this out. :) – Guilherme Raguzzoni Nov 17 '15 at 00:07
  • Well, I can't really speculate why you're having a problem with your filter - it could be anything. I would do two things: Firstly, in UpdateFilter, add the filter expression once it has been generated to a TMemo so you can see exactly what it is. The point is that the IDE's watch window, etc, add additional quote marks when it shows a string which can be confusing. The other thing would be to post a new q showing the exact code you're using and some sample data in the dataset which illustrate the problem. "Why isn't this filter working?" is a different q than "How do I filter?" – MartynA Nov 17 '15 at 07:53