MyBaseを試してみる。(グループ化)
TClientDataSetのグループ化については、Helpに解説がありますが、これが私にとって大変難解な文章です。図を見ていると、できることはわかるのですけど、では実際どうしたらいいのかがさっぱり理解できません。
Embarcadero Product Documentation Wikis
インデックスを使ってデータをグループ化する
とりあえず試してみました。まずグループ化を使わずに普通にプログラムするとこんな感じです。
同じデータがある場合、普通に表示するとDBGridでは、次のように表示されます。
グループ化すると同じデータは、一度だけ描画されるだけになり、見やすくなるということで、次のように修正しました。
各レコード毎に表示されていたITEMがすっきりとしています。 又、Delphiを選んだ場合、Rad Studioを選んだ場合と異なったアイテム数、合計金額が表示されます。このことから、同じITEMに対して処理がされていることがわかります。
KINDフィールドも同じものが並んでいるので、こちらもグループ化させるために次のようにプログラムを修正しました。
これでKINDもグループ化された表示になりました。集合フィールドで設定したGroupingLevelによって、 ITEM数、合計金額についてもKINDに対して処理がされています。ここでようやくヘルプの「グループ化レベルは,インデックス内の項目順序に対応しています。 」の意味が理解できました(^-^)
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に対して処理がされています。ここでようやくヘルプの「グループ化レベルは,インデックス内の項目順序に対応しています。 」の意味が理解できました(^-^)
| 固定リンク