MyBaseを試してみる。(グループ化)
Embarcadero Product Documentation Wikis
インデックスを使ってデータをグループ化する
とりあえず試してみました。まずグループ化を使わずに普通にプログラムするとこんな感じです。
// サンプルデータを追加します。
procedure MakeSample(CDS: TClientDataSet);
var
F: Boolean;
begin
F := CDS.Active;
if not F then
CDS.Open;
try
// サンプルデータの追加
with CDS do
begin
Appendrecord(['Delphi', 'ESD','Starter',18000]);
Appendrecord(['Delphi', 'ESD','Professional',94000]);
Appendrecord(['Delphi', 'ESD','Enterprise',236000]);
Appendrecord(['Delphi', 'ESD','Ultimate',356000]);
Appendrecord(['Delphi', 'ESD','Architect',416000]);
Appendrecord(['RAD Studio', 'ESD','Professional',148000]);
Appendrecord(['RAD Studio', 'ESD','Enterprise',336000]);
Appendrecord(['RAD Studio', 'ESD','Ultimate',456000]);
Appendrecord(['RAD Studio', 'ESD','Architect',516000]);
Appendrecord(['Delphi', 'Package','Professional',98000]);
Appendrecord(['Delphi', 'Package','Enterprise',240000]);
Appendrecord(['Delphi', 'Package','Architect',420000]);
Appendrecord(['RAD Studio', 'Package','Professional',152000]);
Appendrecord(['RAD Studio', 'Package','Enterprise',340000]);
Appendrecord(['RAD Studio', 'Package','Architect',520000]);
CheckBrowseMode;
end;
finally
if not F then
CDS.Close;
end;
end;
// データベースの作成
procedure CreateDB(CDS: TClientDataSet);
var
I: Integer;
begin
// データベースの作成
CDS.Close;
CDS.FieldDefs.Add('ITEM',ftWideString,20);
CDS.FieldDefs.Add('KIND',ftWideString,20);
CDS.FieldDefs.Add('DETAIL',ftWideString,20);
CDS.FieldDefs.Add('PRICE',ftCurrency);
with CDS.IndexDefs.AddIndexDef do
begin
Name := 'IDX';
Fields := 'ITEM;KIND';
end;
CDS.CreateDataSet;
CDS.Close;
for I := 0 to CDS.FieldDefs.Count - 1 do
CDS.FieldDefs[I].CreateField(CDS);
// 集合フィールド
with TAggregateField.Create(CDS) do
begin
AlignMent := taRightJustify;
FieldKind := fkAggregate;
FieldName := 'COUNT';
IndexName := 'IDX';
Expression := 'COUNT(PRICE)';
Active := True;
DataSet := CDS;
end;
with TAggregateField.Create(CDS) do
begin
AlignMent := taRightJustify;
FieldKind := fkAggregate;
FieldName := 'TOTAL_PRICE';
IndexName := 'IDX';
Expression := 'SUM(PRICE)';
Active := True;
DataSet := CDS;
end;
CDS.AggregatesActive := True;
// インデックスの設定
CDS.IndexName := 'IDX';
// 表示用にフィールド幅を設定
CDS.FieldByName('ITEM').DisplayWidth := 10;
CDS.FieldByName('KIND').DisplayWidth := 10;
CDS.FieldByName('DETAIL').DisplayWidth := 15;
CDS.FieldByName('PRICE').DisplayWidth := 8;
// CDS.AggregatesActive := True;
// DBEditの設定
Form1.DBEdit1.DataField := 'COUNT';
Form1.DBEdit2.DataField := 'TOTAL_PRICE';
CDS.Open;
// サンプルデータの作成
MakeSample(CDS);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
CreateDB(ClientDataSet1);
end;
同じデータがある場合、普通に表示するとDBGridでは、次のように表示されます。
グループ化すると同じデータは、一度だけ描画されるだけになり、見やすくなるということで、次のように修正しました。
// データベースの作成
procedure CreateDB(CDS: TClientDataSet);
var
I: Integer;
begin
// データベースの作成
CDS.Close;
CDS.FieldDefs.Add('ITEM',ftWideString,20);
CDS.FieldDefs.Add('KIND',ftWideString,20);
CDS.FieldDefs.Add('DETAIL',ftWideString,20);
CDS.FieldDefs.Add('PRICE',ftCurrency);
with CDS.IndexDefs.AddIndexDef do
begin
Name := 'IDX';
Fields := 'ITEM;KIND';
GroupingLevel := 1;
end;
CDS.CreateDataSet;
CDS.Close;
for I := 0 to CDS.FieldDefs.Count - 1 do
CDS.FieldDefs[I].CreateField(CDS);
// 集合フィールド
with TAggregateField.Create(CDS) do
begin
AlignMent := taRightJustify;
FieldKind := fkAggregate;
FieldName := 'COUNT';
GroupingLevel := 1;
IndexName := 'IDX';
Expression := 'COUNT(PRICE)';
Active := True;
DataSet := CDS;
end;
with TAggregateField.Create(CDS) do
begin
AlignMent := taRightJustify;
FieldKind := fkAggregate;
FieldName := 'TOTAL_PRICE';
GroupingLevel := 1;
IndexName := 'IDX';
Expression := 'SUM(PRICE)';
Active := True;
DataSet := CDS;
end;
CDS.AggregatesActive := True;
// インデックスの設定
CDS.IndexName := 'IDX';
// 表示用にフィールド幅を設定
CDS.FieldByName('ITEM').DisplayWidth := 10;
CDS.FieldByName('KIND').DisplayWidth := 10;
CDS.FieldByName('DETAIL').DisplayWidth := 15;
CDS.FieldByName('PRICE').DisplayWidth := 8;
// グループ化されたフィールドの表示設定
CDS.FieldByName('ITEM').OnGetText := Form1.ITEMGetText;
// DBEditの設定
Form1.DBEdit1.DataField := 'COUNT';
Form1.DBEdit2.DataField := 'TOTAL_PRICE';
CDS.Open;
// サンプルデータの作成
MakeSample(CDS);
end;
// ITEM表示用
procedure TForm1.ITEMGetText(Sender: TField; var Text: string;
DisplayText: Boolean);
begin
// GetGroupStateについて Helpより引用
//
// "AggregatesActive が false の場合,または現在の
// インデックスがグループ化をサポートしていない場合,
// GetGroupState は空のセットを返します。"
// 同じITEMの場合、一番最初のみ表示
if (gbFirst in ClientDataSet1.GetGroupState(1)) then
Text := Sender.AsString
else
Text := '';
end;
各レコード毎に表示されていたITEMがすっきりとしています。 又、Delphiを選んだ場合、Rad Studioを選んだ場合と異なったアイテム数、合計金額が表示されます。このことから、同じITEMに対して処理がされていることがわかります。
KINDフィールドも同じものが並んでいるので、こちらもグループ化させるために次のようにプログラムを修正しました。
// データベースの作成
procedure CreateDB(CDS: TClientDataSet);
var
I: Integer;
begin
// データベースの作成
CDS.Close;
CDS.FieldDefs.Add('ITEM',ftWideString,20);
CDS.FieldDefs.Add('KIND',ftWideString,20);
CDS.FieldDefs.Add('DETAIL',ftWideString,20);
CDS.FieldDefs.Add('PRICE',ftCurrency);
with CDS.IndexDefs.AddIndexDef do
begin
Name := 'IDX';
Fields := 'ITEM;KIND';
GroupingLevel := 2;
end;
CDS.CreateDataSet;
CDS.Close;
for I := 0 to CDS.FieldDefs.Count - 1 do
CDS.FieldDefs[I].CreateField(CDS);
// 集合フィールド
with TAggregateField.Create(CDS) do
begin
AlignMent := taRightJustify;
FieldKind := fkAggregate;
FieldName := 'COUNT';
GroupingLevel := 2;
IndexName := 'IDX';
Expression := 'COUNT(PRICE)';
Active := True;
DataSet := CDS;
end;
with TAggregateField.Create(CDS) do
begin
AlignMent := taRightJustify;
FieldKind := fkAggregate;
FieldName := 'TOTAL_PRICE';
GroupingLevel := 2;
IndexName := 'IDX';
Expression := 'SUM(PRICE)';
Active := True;
DataSet := CDS;
end;
CDS.AggregatesActive := True;
// インデックスの設定
CDS.IndexName := 'IDX';
// 表示用にフィールド幅を設定
CDS.FieldByName('ITEM').DisplayWidth := 10;
CDS.FieldByName('KIND').DisplayWidth := 10;
CDS.FieldByName('DETAIL').DisplayWidth := 15;
CDS.FieldByName('PRICE').DisplayWidth := 8;
// グループ化されたフィールドの表示設定
CDS.FieldByName('ITEM').OnGetText := Form1.ITEMGetText;
CDS.FieldByName('KIND').OnGetText := Form1.KINDGetText;
// CDS.AggregatesActive := True;
// DBEditの設定
Form1.DBEdit1.DataField := 'COUNT';
Form1.DBEdit2.DataField := 'TOTAL_PRICE';
CDS.Open;
// サンプルデータの作成
MakeSample(CDS);
end;
procedure TForm1.KINDGetText(Sender: TField; var Text: string;
DisplayText: Boolean);
begin
// 同じKINDの場合、一番最初のみ表示
if (gbFirst in ClientDataSet1.GetGroupState(2)) then
Text := Sender.AsString
else
Text := '';
end;
これでKINDもグループ化された表示になりました。集合フィールドで設定したGroupingLevelによって、 ITEM数、合計金額についてもKINDに対して処理がされています。ここでようやくヘルプの「グループ化レベルは,インデックス内の項目順序に対応しています。 」の意味が理解できました(^-^)
| 固定リンク
