« MyBaseを試してみる。(インデックスを使わずに、行の追加、挿入、削除編) | トップページ | MyBaseを試してみる。(インデックスを使って、行の追加、挿入、削除編) »

MyBaseを試してみる。(Index、FilterでAggregateが変!?)

Index、Filterを設定するとAggregateの値がおかしくなります。どこか使い方が間違ってるのかな?よくわからないけど、Aggregateを使うときには、このことに注意が必要です。

起動時画面

Incorrect_total1

★Filterプロパティを使った場合
その1
1.[ITEMでソート]を押すと、ITEMでソートされて、合計金額は表示されません。
  ITEMでの並び替えは、合計金額の計算に影響はないでしょうって言いたく
  なりますが、表示されないなら別にいいけどー(^-^)

Incorrect_total11

2.[ORD_IDXでソート]を押すと、再度、合計金額が表示されます。

Incorrect_total12

3.フィルター[ON]を押すと、フィルター処理された合計金額が表示されます。

Incorrect_total13

4.ここで[ITEMでソート]を押すと、なんと合計金額は2倍になりました。

Incorrect_total14

5.驚いて[ORD_IDXでソート]を押すと、合計金額は3倍になりました。

Incorrect_total15

6.これはいけないと思い、フィルター[OFF]を押すと元に戻りました。

Incorrect_total16



その2
1.フィルター[ON]を押して、フィルター処理後の合計金額が正しいことを確認します。

Incorrect_total21

2.フィルター[OFF]を押して、合計金額が正しいことを確認します。

Incorrect_total22

3.[ITEMでソート]を押すと、なんと合計金額は2倍になりました。

Incorrect_total23

4.驚いて[ORD_IDXでソート]を押すと、合計金額は3倍になりました。

Incorrect_total24

5.再び[ITEMでソート]を押すと、なんと合計金額は、4倍になりました。

Incorrect_total25

6.もう一度[ORD_IDXでソート]を押すと、なんと合計金額は、5倍になりました。

Incorrect_total26

[ITEMでソート]、[ORD_IDXでソート]を交互に押すと、合計金額はとどまるところを
知らないようです。(^-^)


★OnFilterRecordを使った場合
その1
1.[ITEMでソート]を押すと・・・ITEMでソートされて、合計金額は表示されません。
2.[ORD_IDXでソート]を押すと・・・再度、合計金額が表示されます。
3.フィルター[ON]を押すと・・・合計金額が表示されません。

Incorrect_total331_2

  しかしここで、次のレコードに移動させるとフィルター処理前の合計金額が
  表示されています。

Incorrect_total332_2

4.ここで[ITEMでソート]を押すと・・・合計金額は表示されません。
5.驚いて[ORD_IDX]を押すと・・・合計金額は表示されません。
6.これはいけないと思い、フィルター[OFF]を押すと・・・合計金額は表示されません。


その2
1.フィルター[ON]を押すと・・・合計金額が表示されません。
  しかしここで、次のレコードに移動させるとフィルター処理前の合計金額が
  表示されました。
2.フィルター[OFF]を押して、合計金額が正しいことを確認します。
  合計金額は正しく表示されました。

Incorrect_total421

  と思ったけど、フィルター処理されたレコードに移動させると、
  合計金額が消えてしまいました。

Incorrect_total422

3.[ITEMでソート]を押すと・・・合計金額は表示されません。
4.驚いて[ORD_IDX]を押すと・・・合計金額は表示されません。
5.[ITEMでソート]を押すと・・・合計金額は表示されません。
6.[ORD_IDXでソート]を押すと・・・合計金額は表示されません。
7.[ITEMでソート]、[ORD_IDXでソート]を交互に押すと・・・
  合計金額は表示されません。


いろいろ試した結果、インデックスを入れ替えず、Filterプロパティでフィルター処理すれば正常な動作をしているようです。フィルター時には、フィルター処理後の合計金額が表示されますし、解除後は、正しい合計金額が表示されました。しかしOnFilterRecordでフィルター処理した場合は、正しく表示されませんでした。
// COMMON

// サンプルデータを追加します。
procedure MakeSample(CDS: TClientDataSet);
var
  No: Integer;
  F: Boolean;
begin
  F := CDS.Active;
  if not F then
    CDS.Open;
  try
    // サンプルデータの追加
    No := 0;
    with CDS do
    begin
      Inc(No);
      Appendrecord([No, 'Delphi XE2 Starter ESD',10,'本',18000]);
      Inc(No);
      Appendrecord([No, 'Delphi XE2 Professional ESD',5,'本',94000]);
      Inc(No);
      Appendrecord([No, 'Delphi XE2 Enterprise ESD',10,'本',236000]);
      Inc(No);
      Appendrecord([No, 'Delphi XE2 Ultimate ESD',3,'本',356000]);
      Inc(No);
      Appendrecord([No, 'Delphi XE2 Architect ESD',1,'本',416000]);
      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,30);
  CDS.FieldDefs.Add('QTY',ftFloat);
  CDS.FieldDefs.Add('UNIT',ftWideString,4);
  CDS.FieldDefs.Add('PRICE',ftCurrency);
  CDS.IndexDefs.Add('ORD_IDX','ORD', [ixPrimary]);
  //CDS.IndexDefs.Add('ITEM_IDX','ITEM', []);
  CDS.CreateDataSet;
  CDS.Close;

  for I := 0 to CDS.FieldDefs.Count - 1 do
    CDS.FieldDefs[I].CreateField(CDS);

  // 計算フィールド
  with TCurrencyField.Create(CDS) do
  begin
    FieldName := 'AMOUNT';
    Visible:=True;
    FieldKind := fkInternalCalc;
    DataSet := CDS;
  end;

  // 集合フィールド
  with TAggregateField.Create(CDS) do
  begin
    DisplayLabel := '合計';
    DisplayWidth := 10;
    DisplayFormat := '#,###,###,###';
    AlignMent := taRightJustify;
    FieldKind := fkAggregate;
    FieldName := 'TOTAL_F';
    ReadOnly := True;
    Expression := 'SUM(AMOUNT)';
    Active := True;
    DataSet := CDS;
  end;
  CDS.AggregatesActive := True;

  // インデックスの設定
  CDS.IndexName := 'ORD_IDX';

  // 表示用にフィールド幅を設定
  CDS.FieldByName('ORD').DisplayWidth := 3;
  CDS.FieldByName('ITEM').DisplayWidth := 25;
  CDS.FieldByName('QTY').DisplayWidth := 3;
  CDS.FieldByName('UNIT').DisplayWidth := 4;
  CDS.FieldByName('PRICE').DisplayWidth := 8;
  CDS.FieldByName('AMOUNT').DisplayWidth := 10;

  // 計算フィールドの設定
  CDS.OnCalcFields := Form1.CalcFields;

  // DBEditの設定
  Form1.DBEdit1.DataField := 'TOTAL_F';
  CDS.Open;

  // サンプルデータの作成
  MakeSample(CDS);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  CreateDB(ClientDataSet1);
end;

procedure TForm1.ClientDataSet1FilterRecord(DataSet: TDataSet;
  var Accept: Boolean);
begin
  Accept := AnsiPos(Edit1.Text, DataSet.FieldByName('ITEM').AsString) > 0;
end;


// 計算フィールド
procedure TForm1.CalcFields(DataSet: TDataSet);
begin
  DataSet.FieldByName('AMOUNT').AsCurrency :=
    DataSet.FieldByName('QTY').AsFloat *
    DataSet.FieldByName('Price').AsCurrency;
end;

// フィルターON
procedure TForm1.SpeedButton3Click(Sender: TObject);
begin
  //ClientDataSet1.Filter := 'ITEM LIKE '+QuotedStr('%'+ Edit1.Text+'%');
  ClientDataSet1.Filtered := True;
end;

// フィルターOFF
procedure TForm1.SpeedButton4Click(Sender: TObject);
begin
  ClientDataSet1.Filtered := False;
  ClientDataSet1.Filter := '';
end;

// インデックス ITEM
procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
  ClientDataSet1.IndexFieldNames := 'ITEM';
  // ClientDataSet1.IndexName := 'ITEM_IDX';
end;

// インデックス ORD_IDX
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  ClientDataSet1.IndexName := 'ORD_IDX';
end;

// Helpより
// メモ:  IndexFieldNames プロパティと
// IndexName プロパティは相互に排他的です。
// 一方を設定するともう一方はクリアされます。

|

« MyBaseを試してみる。(インデックスを使わずに、行の追加、挿入、削除編) | トップページ | MyBaseを試してみる。(インデックスを使って、行の追加、挿入、削除編) »