Советы по Delphi

Как заставить DBGrid сортировать данные по щелчку на заголовке столбца?


Nomadic советует:

Кyсочек кода, чтобы повесить на clickable столбец RxGrid, показывающий RxQuery с опpеделенным макpосом %Order. Работать не бyдет (без модyлей), но в качестве идеи может быть полезен.

    unit vgRXutil;

interface

uses

SysUtils, Classes, DB, DBTables, rxLookup, RxQuery;



{ TrxDBLookup }
procedure RefreshRXLookup(Lookup: TrxLookupControl);
procedure RefreshRXLookupLookupSource(Lookup: TrxLookupControl);

function RxLookupValueInteger(Lookup: TrxLookupControl): Integer;

{ TRxQuery }

{ Applicatable to SQL's without SELECT * syntax }

{ Inserts FieldName into first position in '%Order' macro and refreshes query }
procedure HandleOrderMacro(Query: TRxQuery; Field: TField);

{ Sets '%Order' macro, if defined, and refreshes query }
procedure InsertOrderBy(Query: TRxQuery; NewOrder: String);

{ Converts list of order fields if defined and refreshes query }
procedure UpdateOrderFields(Query: TQuery; OrderFields: TStrings);

implementation
uses
vgUtils, vgDBUtl, vgBDEUtl;

{ TrxDBLookup refresh }

type
TRXLookupControlHack = class(TrxLookupControl)
property DataSource;
property LookupSource;
property Value;
property EmptyValue;
end;

procedure RefreshRXLookup(Lookup: TrxLookupControl);
var
SaveField: String;
begin
with
TRXLookupControlHack(Lookup) do
begin

SaveField := DataField;
DataField := '';
DataField := SaveField;
end;
end;

procedure RefreshRXLookupLookupSource(Lookup: TrxLookupControl);
var
SaveField: String;
begin
with
TRXLookupControlHack(Lookup) do
begin

SaveField := LookupDisplay;
LookupDisplay := '';
LookupDisplay := SaveField;
end;
end;

function RxLookupValueInteger(Lookup: TrxLookupControl): Integer;
begin
with
TRXLookupControlHack(Lookup) do
try
if
Value <> EmptyValue then
Result := StrToInt(Value) else
Result := 0;
except
Result := 0;
end;
end;

procedure InsertOrderBy(Query: TRxQuery; NewOrder: String);
var
Param: TParam;
OldActive: Boolean;
OldOrder: String;
Bmk: TPKBookMark;
begin
Param := FindParam(Query.Macros, 'Order');
if not Assigned(Param) then Exit;

OldOrder := Param.AsString;

if OldOrder <> NewOrder then
begin

OldActive := Query.Active;
if OldActive then Bmk := GetPKBookmark(Query, '');
try
Query.Close;
Param.AsString := NewOrder;
try
Query.Prepare;
except
Param.AsString := OldOrder;
end;
Query.Active := OldActive;
if OldActive then SetToPKBookMark(Query, Bmk);
finally
if
OldActive then FreePKBookmark(Bmk);
end;
end;
end;

procedure UpdateOrderFields(Query: TQuery; OrderFields: TStrings);
var
NewOrderFields: TStrings;

procedure AddOrderField(S: String);
begin
if
NewOrderFields.IndexOf(S) < 0 then
NewOrderFields.Add(S);
end;

var
I, J: Integer;
Field: TField;
FieldDef: TFieldDef;
S: String;
begin
NewOrderFields := TStringList.Create;
with Query do
try
for
I := 0 to OrderFields.Count - 1 do
begin

S := OrderFields[I];
Field := FindField(S);
if Assigned(Field) and (Field.FieldNo > 0) then
AddOrderField(IntToStr(Field.FieldNo))
else
try

J := StrToInt(S);
if J < FieldDefs.Count then
AddOrderField(IntToStr(J));
except
end
;
end;
OrderFields.Assign(NewOrderFields);
finally
NewOrderFields.Free;
end;
end;

procedure HandleOrderMacro(Query: TRxQuery; Field: TField);
var
Param: TParam;
Tmp, OldOrder, NewOrder: String;
I: Integer;
C: Char;
TmpField: TField;
OrderFields: TStrings;
begin
Param := FindParam(Query.Macros, 'Order');
if not Assigned(Param) or Field.Calculated or Field.Lookup then Exit;
OldOrder := Param.AsString;
I := 0;
Tmp := '';
OrderFields := TStringList.Create;
try
OrderFields.Ad(Field.FieldName);
while I < Length(OldOrder) do
begin

Inc(I);
C := OldOrder[I];
if C in FieldNameChars then
Tmp := Tmp + C;

if (not (C in FieldNameChars) or (I = Length(OldOrder))) and (Tmp <> '') then
begin

TmpField := Field.DataSet.FindField(Tmp);
if OrderFields.IndexOf(Tmp) < 0 then
OrderFields.Add(Tmp);
Tmp := '';
end;
end;

UpdateOrderFields(Query, OrderFields);
NewOrder := OrderFields[0];
for I := 1 to OrderFields.Count - 1 do
NewOrder := NewOrder + ', ' + OrderFields[1];
finally
OrderFields.Free;
end;
InsertOrderBy(Query, NewOrder);
end;

end.

[001242]



Содержание раздела