MyBaseを試してみる。(フィルター編)
特にMyBaseの場合、今までOnFilterRecordでごちゃごちゃ書いていた処理も、計算フィールドと組み合わせるとシンプルな処理にできます。今回のサンプルも、いつもように「コテコテなコード」で「コテコテなフィルター条件」ですが、MyBaseの性質上、数万のレコードであっても瞬時にフィルター処理されます。
使えるフィルター条件式は、ヘルプを参照して下さい。
Embarcadero Product Documentation Wikis
DBClient.TClientDataSet.Filter
http://docwiki.embarcadero.com/VCL/ja/DBClient.TClientDataSet.Filter
procedure MakeSample(CDS: TClientDataSet);
var
F: Boolean;
begin
F := CDS.Active;
if not F then
CDS.Open;
try
// サンプルデータの追加
with CDS do
begin
Appendrecord([ 1,'基礎 普通コンクリート',150]);
Appendrecord([ 2,'躯体 普通コンクリート',800]);
Appendrecord([ 3,'AW-1 引違窓',30]);
Appendrecord([ 4,'AW-2 2連外倒し排煙窓',10]);
Appendrecord([ 5,'床 モルタル金鏝押エ t=30',400]);
Appendrecord([ 6,'床 コンクリート金鏝押エ',300]);
Appendrecord([ 7,'壁 ビニールクロス貼',1500]);
Appendrecord([ 8,'柱 ビニールクロス貼',100]);
Appendrecord([ 9,'梁 クロス貼',50]);
Appendrecord([10,'天井 ビニールクロス貼',500]);
Appendrecord([11,'土間 モルタル鏝押エ',100]);
CheckBrowseMode;
end;
finally
if not F then
CDS.Close;
end;
end;
// データベースの作成
procedure CreateDB(CDS: TClientDataSet);
var
I: Integer;
begin
// データベースの作成
CDS.Close;
CDS.FieldDefs.Add('ORD' ,ftInteger);
CDS.FieldDefs.Add('ITEM',ftWideString,20);
CDS.FieldDefs.Add('QTY' ,ftInteger);
CDS.IndexDefs.Add('ORD_IDX','ORD', [ixPrimary]);
CDS.CreateDataSet;
CDS.Close;
for I := 0 to CDS.FieldDefs.Count - 1 do
CDS.FieldDefs[I].CreateField(CDS);
// 計算フィールド
with TWideStringField.Create(CDS) do
begin
FieldName := 'STRFORFILTER';
Visible:=True;
FieldKind := fkInternalCalc;
DataSet := CDS;
end;
// インデックスの設定
CDS.IndexName := 'ORD_IDX';
// サンプルデータの作成
MakeSample(CDS);
end;
// 文字列の比較用文字列を作成します。
// アルファベットは全角大文字、
// 半角カタカナ、全角カタカナは、全角ひらがなとします。
function MakeHikakuMoji(S: String): String;
// 文字の変換
function MapString(const Source: string; Flag: Integer): string;
var
Chr: array [0..255] of Char;
begin
LCMapString(GetUserDefaultLCID(), Flag, PChar(Source),
Length(Source) + 1, Chr, Sizeof(Chr));
Result := chr;
end;
begin
Result := AnsiUpperCase(MapString(S, LCMAP_FULLWIDTH or LCMAP_HIRAGANA));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
CreateDB(ClientDataSet1);
ClientDataSet1.Open;
end;
// 計算フィールド
procedure TForm1.ClientDataSet1CalcFields(DataSet: TDataSet);
begin
if DataSet.Active then
begin
DataSet.FieldByName('STRFORFILTER').AsString :=
MakeHikakuMoji(DataSet.FieldByName('ITEM').AsString);
end;
end;
// フィルター
procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
// フィルター用計算フィールド(STRFORFILTER)を使う場合
function GetFilterStr(S: String): String;
const
M1 = 'STRFORFILTER LIKE ';
L1 = 'NOT';
L2 = 'OR';
var
SL: TStringList;
I: Integer;
S1,S2, S3: String;
begin
Result := '';
// フィルター文字列の変換
S := StringReplace(MakeHikakuMoji(S), ' ',' ', [rfReplaceAll]);
SL := TStringList.Create;
try
SL.Delimiter := ' ';
SL.StrictDelimiter := True;
SL.DelimitedText := S;
for I := 0 to SL.Count -1 do
begin
S1 := Trim(SL[I]);
if S1 <> '' then
begin
if (S1 <> L1) and (S1 <> L2) then
begin
if S2 = L1 then
S3 := Concat('( NOT (', M1, QuotedStr('%' + S1 +'%'), ')) ')
else
S3 := Concat('(', M1, QuotedStr('%' + S1 +'%'), ') ');
if I = 0 then
Result := S3
else if (S2 = L2) then
Result := Result + ' OR ' + S3
else
Result := Result + ' AND ' + S3;
S2 := '';
end
else
S2 := S1;
end;
end;
finally
SL.Free;
end;
end;
var
S: String;
begin
if Key = VK_RETURN then
begin
if CheckBox1.Checked then
S := Edit1.Text
else
S := GetFilterStr(Trim(Edit1.Text));
// フィルター処理をします。
ClientDataSet1.Filter := S;
ClientDataSet1.Filtered :=True;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ClientDataSet1.Filtered := False;
end;
起動時
QTYフィールドで、フィルター処理
ITEMフィールドでフィルター処理
フィルター用に作成した計算フィールドでフィルター処理
| 固定リンク

