palin2000
asked on
DBGrid filtering
Hi
Is there a component or code available that could be applied to Delphi's DBGrid to emulate the way MS Excel "Auto Filters" its spreadsheet. i.e. produces a list of values in a drop-down box for each colunm in the first row?.
All comments welcome.
Rgds Palin
Is there a component or code available that could be applied to Delphi's DBGrid to emulate the way MS Excel "Auto Filters" its spreadsheet. i.e. produces a list of values in a drop-down box for each colunm in the first row?.
All comments welcome.
Rgds Palin
ASKER
Hi nnbbb09
Thanks for reply, excellent suite of components but far too expensive.
Any other suggestions?
Rgds Palin
Thanks for reply, excellent suite of components but far too expensive.
Any other suggestions?
Rgds Palin
not perfect, but mayby an idea
unit dbg_filter_u;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Grids, DBGrids, DBTables, Db, StdCtrls;
type
TForm1 = class(TForm)
Table1: TTable;
DataSource1: TDataSource;
Query1: TQuery;
DBGrid1: TDBGrid;
cbFilterBox: TComboBox; //a hidden combobox (Style = csDropDownList)
procedure Table1AfterOpen(DataSet: TDataSet);
procedure Table1AfterPost(DataSet: TDataSet);
procedure DBGrid1TitleClick(Column: TColumn);
procedure cbFilterBoxChange(Sender: TObject);
procedure cbFilterBoxClick(Sender: TObject);
procedure cbFilterBoxExit(Sender: TObject);
private
Procedure FillPickLists(ADBGrid : TDBGrid);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//For Accessing some Protected Methods
type TCDBGrid = class(TCustomDBGrid);
//Storing the Values into the Picklist-Propertys of the asscociated Columns,
//this may cost time depending on the amount of the dataset
Procedure TForm1.FillPickLists(ADBGr id : TDBGrid);
const
SQL_Text = 'Select Distinct %s From %s';
var
q : TQuery;
i : integer;
Begin
If (Assigned(ADBGrid)) and
(Assigned(ADBGrid.Datasour ce)) and
(Assigned(ADBGrid.Datasour ce.DataSet )) Then
Begin
If (ADBGrid.Datasource.DataSe t is ttable) Then
begin
q := TQuery.Create(self);
try
try
q.DatabaseName := TTable(ADBGrid.Datasource. DataSet).D ataBaseNam e;
for i := 0 to ADBGrid.Columns.Count - 1 do //for each column
begin
if ADBGrid.Columns[i].Field.F ieldKind = fkData then //only physical fields
begin
ADBGrid.Columns[i].ButtonS tyle := cbsNone; //avoid button-showing
ADBGrid.Columns[i].PickLis t.Clear;
q.Close;
q.SQL.text := Format(SQL_Text,[ADBGrid.C olumns[i]. Field.Fiel dName,TTab le(ADBGrid .Datasourc e.DataSet) .TableName ]);
q.Open;
While not q.eof do
begin
ADBGrid.Columns[i].PickLis t.Add(q.Fi elds[0].As String);
q.next;
end;
q.close;
end;
end;
finally
q.free;
end;
except
raise;
end;
end else
Raise exception.Create('This Version works only for TTables');
end else
Raise Exception.Create('Grid not properly Assigned');
end;
//Initial-Fill
procedure TForm1.Table1AfterOpen(Dat aSet: TDataSet);
begin
FillPickLists(DBGrid1);
end;
//Refill after a change
procedure TForm1.Table1AfterPost(Dat aSet: TDataSet);
begin
FillPickLists(DBGrid1);
end;
//Show a Dropdownbox for selecting, instead the title on Titleclick
procedure TForm1.DBGrid1TitleClick(C olumn: TColumn);
var
ARect : Trect;
DummyTC : TColumn;
begin
If column.PickList.Count > 0 then
begin
cbFilterbox.Items.Assign(c olumn.Pick List);
ARect := TCDBGrid(Column.Grid).Calc TitleRect( Column,0,D ummyTC);
cbfilterBox.top := Column.Grid.Top+1;
cbfilterBox.left := Column.Grid.left+Arect.Lef t+1;
cbFilterbox.Width := Column.Width;
cbFilterBox.Tag := Integer(Column); //Store the columnPointer
cbFilterBox.Show;
cbFilterBox.BringToFront;
cbFilterBox.DroppedDown := True;
end;
end;
//Build up the Filter
procedure TForm1.cbFilterBoxChange(S ender: TObject);
begin
cbFilterBox.Hide;
if cbFilterBox.Text <> TColumn(cbFilterBox.Tag).T itle.Capti on then
begin
Case TColumn(cbFilterBox.Tag).F ield.DataT ype of
//Some Fieldtypes
ftstring :
TTable(TDBGrid(TColumn(cbF ilterBox.T ag).Grid). Datasource .Dataset). Filter :=
TColumn(cbFilterBox.Tag).F ield.Field Name+' = '+QuotedStr(cbFilterBox.Te xt);
ftInteger,
ftFloat :
TTable(TDBGrid(TColumn(cbF ilterBox.T ag).Grid). Datasource .Dataset). Filter :=
TColumn(cbFilterBox.Tag).F ield.Field Name+' = '+cbFilterBox.Text;
end;
TTable(TDBGrid(TColumn(cbF ilterBox.T ag).Grid). Datasource .Dataset). Filtered := True;
end;
end;
//some Hiding-events
procedure TForm1.cbFilterBoxClick(Se nder: TObject);
begin
cbFilterBox.Hide;
end;
procedure TForm1.cbFilterBoxExit(Sen der: TObject);
begin
cbFilterBox.Hide;
end;
end.
meikl ;-)
unit dbg_filter_u;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Grids, DBGrids, DBTables, Db, StdCtrls;
type
TForm1 = class(TForm)
Table1: TTable;
DataSource1: TDataSource;
Query1: TQuery;
DBGrid1: TDBGrid;
cbFilterBox: TComboBox; //a hidden combobox (Style = csDropDownList)
procedure Table1AfterOpen(DataSet: TDataSet);
procedure Table1AfterPost(DataSet: TDataSet);
procedure DBGrid1TitleClick(Column: TColumn);
procedure cbFilterBoxChange(Sender: TObject);
procedure cbFilterBoxClick(Sender: TObject);
procedure cbFilterBoxExit(Sender: TObject);
private
Procedure FillPickLists(ADBGrid : TDBGrid);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//For Accessing some Protected Methods
type TCDBGrid = class(TCustomDBGrid);
//Storing the Values into the Picklist-Propertys of the asscociated Columns,
//this may cost time depending on the amount of the dataset
Procedure TForm1.FillPickLists(ADBGr
const
SQL_Text = 'Select Distinct %s From %s';
var
q : TQuery;
i : integer;
Begin
If (Assigned(ADBGrid)) and
(Assigned(ADBGrid.Datasour
(Assigned(ADBGrid.Datasour
Begin
If (ADBGrid.Datasource.DataSe
begin
q := TQuery.Create(self);
try
try
q.DatabaseName := TTable(ADBGrid.Datasource.
for i := 0 to ADBGrid.Columns.Count - 1 do //for each column
begin
if ADBGrid.Columns[i].Field.F
begin
ADBGrid.Columns[i].ButtonS
ADBGrid.Columns[i].PickLis
q.Close;
q.SQL.text := Format(SQL_Text,[ADBGrid.C
q.Open;
While not q.eof do
begin
ADBGrid.Columns[i].PickLis
q.next;
end;
q.close;
end;
end;
finally
q.free;
end;
except
raise;
end;
end else
Raise exception.Create('This Version works only for TTables');
end else
Raise Exception.Create('Grid not properly Assigned');
end;
//Initial-Fill
procedure TForm1.Table1AfterOpen(Dat
begin
FillPickLists(DBGrid1);
end;
//Refill after a change
procedure TForm1.Table1AfterPost(Dat
begin
FillPickLists(DBGrid1);
end;
//Show a Dropdownbox for selecting, instead the title on Titleclick
procedure TForm1.DBGrid1TitleClick(C
var
ARect : Trect;
DummyTC : TColumn;
begin
If column.PickList.Count > 0 then
begin
cbFilterbox.Items.Assign(c
ARect := TCDBGrid(Column.Grid).Calc
cbfilterBox.top := Column.Grid.Top+1;
cbfilterBox.left := Column.Grid.left+Arect.Lef
cbFilterbox.Width := Column.Width;
cbFilterBox.Tag := Integer(Column); //Store the columnPointer
cbFilterBox.Show;
cbFilterBox.BringToFront;
cbFilterBox.DroppedDown := True;
end;
end;
//Build up the Filter
procedure TForm1.cbFilterBoxChange(S
begin
cbFilterBox.Hide;
if cbFilterBox.Text <> TColumn(cbFilterBox.Tag).T
begin
Case TColumn(cbFilterBox.Tag).F
//Some Fieldtypes
ftstring :
TTable(TDBGrid(TColumn(cbF
TColumn(cbFilterBox.Tag).F
ftInteger,
ftFloat :
TTable(TDBGrid(TColumn(cbF
TColumn(cbFilterBox.Tag).F
end;
TTable(TDBGrid(TColumn(cbF
end;
end;
//some Hiding-events
procedure TForm1.cbFilterBoxClick(Se
begin
cbFilterBox.Hide;
end;
procedure TForm1.cbFilterBoxExit(Sen
begin
cbFilterBox.Hide;
end;
end.
meikl ;-)
ASKER
meikl
Excellent piece of coding, I can learn from this as well as hopefully solving my request.
As yet I've not got it to run so could you check I'm doing everything I need to get it to work.
It's failing to compile at the following line of code:
ARect := TCDBGrid(Column.Grid).Calc TitleRect( Column,0,D ummyTC);
Problem with CalcTitleRect, any ideas?.
I am doing this correctly, placing the following components on form:
TTable (Tablel1)- setting it to DBDemos & OrdersDB Active True
TDataSource (DataSource1) - setting it to Table1
DBGrid1 - setting it to DataSource1
TQuery (Query1) - not set to anything, unsure as you have Query1 Create(self) in code
TComboBox (cbFilterBox) - set as csDropDownList
I'd really like to get this to work could you check I've not missed something obvious like setting part of your code, not stated by yourself because you expected me to know without saying. For instance should I be adding to this piece of code "SQL_Text = 'Select Distinct %s From %s';"
Please treat me like an idiot or at the best a beginner(of which I am).
Thank you for your time.
Rgds Palin
Excellent piece of coding, I can learn from this as well as hopefully solving my request.
As yet I've not got it to run so could you check I'm doing everything I need to get it to work.
It's failing to compile at the following line of code:
ARect := TCDBGrid(Column.Grid).Calc
Problem with CalcTitleRect, any ideas?.
I am doing this correctly, placing the following components on form:
TTable (Tablel1)- setting it to DBDemos & OrdersDB Active True
TDataSource (DataSource1) - setting it to Table1
DBGrid1 - setting it to DataSource1
TQuery (Query1) - not set to anything, unsure as you have Query1 Create(self) in code
TComboBox (cbFilterBox) - set as csDropDownList
I'd really like to get this to work could you check I've not missed something obvious like setting part of your code, not stated by yourself because you expected me to know without saying. For instance should I be adding to this piece of code "SQL_Text = 'Select Distinct %s From %s';"
Please treat me like an idiot or at the best a beginner(of which I am).
Thank you for your time.
Rgds Palin
hi palin,
well the tquery is obsolete in my sample and can be deleted,
about the calctitlerect, that is a protected method of TCustomDBGrid (in delphi 5),
to access this method, i've defined a type TCDBGrid for a typecast
this declaration is
type TCDBGrid = Class(TCustomDBGrid);
at the beginning of the implementation part
calctitlerect is needed to get the current postion of the title in the grid,
where to place the combobox instead.
atleast this method is defined in the delphi 5 version and may not available in earlier version
(don't know about d4, but d3 didn't have this method). if you don't have d5,
then the CellRect-Method from TCustomGrid could be used instead.
if you leave your email, then i could send you a better commented running sample based on DBDemos/Orders.DB
including filter-capactity of Date and Currency fields.
about
SQL_Text = 'Select Distinct %s From %s';
%s are placeholders, which are replaced with field- and tablename
with the format-function at runtime,
no changes needed
the query (i use a runtime-created) is needed to collect the unique fieldvalues of one column
tell me what delphi version you use
meikl ;-)
well the tquery is obsolete in my sample and can be deleted,
about the calctitlerect, that is a protected method of TCustomDBGrid (in delphi 5),
to access this method, i've defined a type TCDBGrid for a typecast
this declaration is
type TCDBGrid = Class(TCustomDBGrid);
at the beginning of the implementation part
calctitlerect is needed to get the current postion of the title in the grid,
where to place the combobox instead.
atleast this method is defined in the delphi 5 version and may not available in earlier version
(don't know about d4, but d3 didn't have this method). if you don't have d5,
then the CellRect-Method from TCustomGrid could be used instead.
if you leave your email, then i could send you a better commented running sample based on DBDemos/Orders.DB
including filter-capactity of Date and Currency fields.
about
SQL_Text = 'Select Distinct %s From %s';
%s are placeholders, which are replaced with field- and tablename
with the format-function at runtime,
no changes needed
the query (i use a runtime-created) is needed to collect the unique fieldvalues of one column
tell me what delphi version you use
meikl ;-)
ASKER
Hi meikl
Thanks again for your reply, I see the problem now as I am in fact still on Delphi 3.
I would appreciate if you would contact me further on this as it has taken my interest as well as solving my request, my e-mail is john.hernan@ntlworld.com
Speak to you soon.
Rgds Palin
Thanks again for your reply, I see the problem now as I am in fact still on Delphi 3.
I would appreciate if you would contact me further on this as it has taken my interest as well as solving my request, my e-mail is john.hernan@ntlworld.com
Speak to you soon.
Rgds Palin
well ok,
i transform the sample down to d3 and
send it to you.
this will take a bit time, but you will get it within 24 hours.
meikl ;-)
i transform the sample down to d3 and
send it to you.
this will take a bit time, but you will get it within 24 hours.
meikl ;-)
ASKER
Thanks meikl look forward to it.
Rgds Palin
Rgds Palin
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hi Meikl
Thanks again for all your help, I'm off now to play with my new grid.
Please accept the points for this question, hope to speak to you again.
Rgds John
Thanks again for all your help, I'm off now to play with my new grid.
Please accept the points for this question, hope to speak to you again.
Rgds John
The QuantumGrid by Developer Express provides Excel style filtering, Outlook Filtering and lots of inplace editors. I think it's quite expensive though. Their web site is http://www.devexpress.com