あなたはFilter
表現の代わりに、OnFilterRecord
ハンドラを使用したい場合は、TClientDataSetには、テキストフィルタに使用するものであるTExprParser
クラスのソースを見てみ価値があります。これは、Delphiソース内のDBCommon.Pasユニットファイルに含まれています。 D7 TExprParser
は、次の機能をサポートしています。
function TExprParser.TokenSymbolIsFunc(const S: string) : Boolean;
begin
Result := (CompareText(S, 'UPPER') = 0) or
(CompareText(S, 'LOWER') = 0) or
[...]
(CompareText(S, 'YEAR') = 0) or
(CompareText(S, 'MONTH') = 0) or
(CompareText(S, 'DAY') = 0) or
[...]
end;
ところで、それはそれはSQLで見つかったIN
構築物についてのサポートのようなものを明らかにするためTExprParser
のソースの残りを見て価値があります。
私の(イギリス)システムでは、日付はDBGridにdd/mm/yyyyとして表示されます。例外を発生させずにフィルター式の全てがD7での作業の下に示し、ことを考えると、期待される結果を返す:あなたが同様の結果を得られない場合は
procedure TForm1.Button1Click(Sender: TObject);
begin
// ADate field of CDS is initialised by
// CDS1.FieldByName('ADate').AsDateTime := Now - random(365);
edFilter.Text := 'ADate = ''10/2/2017'''; // works, date format = dd/mm/yyyy
edFilter.Text := 'Month(ADate) = 2'; // works
edFilter.Text := 'Year(ADate) = 2017'; // works
edFilter.Text := '(Day(ADate) = 10) and (Year(ADate) = 2017)'; // works
CDS1.Filtered := False;
CDS1.Filter := edFilter.Text;
CDS1.Filtered := True;
end;
、私はあなたがあなたの地域を見てから始めることをお勧めしたいですTDBGridに日付を表示する方法について説明します。
フィルタ式は、フィルタリングの代替方法、つまりOnFilterRecord
イベントを使用する場合に比べて特に効率的ではありません。
イベントハンドラでは、たとえばDecodeDateTime
を入力してYear、Month、Dayなどのコンポーネントにデコードし、好きなテストをその値に適用します。次に、Accept
をTrueまたはFalseに設定します。
更新は、私はあなたがこのとしていた問題は TExprParser.TokenSymbolIsFunc()
でサポートされている日付関数は、ユーザーの言語ではないということであったことをここに答え Delphi: check if Record of DataSet is visible or filtered にあなたのコメントから集まります。
以下のコードを使用して、フィルタ式の日付関数名を変換することができます。 それはなぜあなたはあなたのクエリに3つの隠された列を追加していない
type
TForm1 = class(TForm)
[...]
public
NameLookUp : TStringList;
[...]
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
NameLookUp := TStringList.Create;
// Assume Y, M & C are the local-language names
NameLookUp.Add('Y=Year');
NameLookUp.Add('M=Month');
NameLookUp.Add('D=Day');
[...]
end;
procedure TForm1.Log(const Title, Msg : String);
begin
Memo1.Lines.Add(Title + ' : ' + Msg);
end;
function TForm1.TranslateExpression(const Input : String; ADataSet : TDataSet) : String;
var
SS : TStringStream;
TokenText : String;
LookUpText : String;
Parser : TParser;
CH : Char;
begin
SS := TStringStream.Create(Input);
Parser := TParser.Create(SS);
Result := '';
try
CH := Parser.Token;
// following translates Input by parsing it using TParser from Classes.Pas
while Parser.Token <> #0 do begin
TokenText := Parser.TokenString;
case CH of
toSymbol : begin
// The following will translate TokenText for symbols
// but only if TokenText is not a FieldName of ADataSet
if ADataSet.FindField(TokenText) = Nil then begin
LookUpText := NameLookUp.Values[TokenText];
if LookUpText <> '' then
Result := Result + LookUpText
else
Result := Result + TokenText;
end
else
Result := Result + TokenText;
end;
toString :
// SingleQuotes surrounding TokenText in Input and ones embedded in it
// will have been stripped, so reinstate the surrounding ones and
// double-up the embedded ones
Result := Result + '''' + StringReplace(TokenText, '''', '''''', [rfReplaceAll]) + '''';
else
Result := Result + TokenText;
end; { case }
if Result <> '' then
Result := Result + ' ';
CH := Parser.NextToken;
end;
finally
Parser.Free;
SS.Free;
end;
Log('TransResult', Result);
end;
procedure TForm1.btnSetFilterExprClick(Sender: TObject);
begin
// Following tested with e.g edFilter.Text =
// LastName = 'aaa' and Y(BirthDate) = 2000
UpdateFilter2;
end;
procedure TForm1.UpdateFilter2;
var
T1 : Integer;
begin
CDS1.OnFilterRecord := Nil;
T1 := GetTickCount;
CDS1.DisableControls;
try
CDS1.Filtered := False;
CDS1.Filter := TranslateExpression(edFilter.Text, CDS1);
if CDS1.Filter <> '' then begin
CDS1.Filtered := True;
end;
Log('Filter update time', IntToStr(GetTickCount - T1) + 'ms');
finally
CDS1.EnableControls;
end;
end;
をどのように動作するかの説明については、埋め込まれたコメントを参照してください:...... edatumの月(抽出、edatum_dayとして(edatumの日)を抽出)edatum_monthとして、edatum_yearとして(edatumの年)を抽出するので、これらのフィールドを非常に簡単にフィルタリングできるようになりましたか? –
タイトルのタグ情報を繰り返す必要はありません。 –