Index、Filterを設定するとAggregateの値がおかしくなります。どこか使い方が間違ってるのかな?よくわからないけど、Aggregateを使うときには、このことに注意が必要です。
起動時画面
★Filterプロパティを使った場合
その1
1.[ITEMでソート]を押すと、ITEMでソートされて、合計金額は表示されません。
ITEMでの並び替えは、合計金額の計算に影響はないでしょうって言いたく
なりますが、表示されないなら別にいいけどー(^-^)
2.[ORD_IDXでソート]を押すと、再度、合計金額が表示されます。
3.フィルター[ON]を押すと、フィルター処理された合計金額が表示されます。
4.ここで[ITEMでソート]を押すと、なんと合計金額は2倍になりました。
5.驚いて[ORD_IDXでソート]を押すと、合計金額は3倍になりました。
6.これはいけないと思い、フィルター[OFF]を押すと元に戻りました。
その2
1.フィルター[ON]を押して、フィルター処理後の合計金額が正しいことを確認します。
2.フィルター[OFF]を押して、合計金額が正しいことを確認します。
3.[ITEMでソート]を押すと、なんと合計金額は2倍になりました。
4.驚いて[ORD_IDXでソート]を押すと、合計金額は3倍になりました。
5.再び[ITEMでソート]を押すと、なんと合計金額は、4倍になりました。
6.もう一度[ORD_IDXでソート]を押すと、なんと合計金額は、5倍になりました。
[ITEMでソート]、[ORD_IDXでソート]を交互に押すと、合計金額はとどまるところを
知らないようです。(^-^)
★OnFilterRecordを使った場合
その1
1.[ITEMでソート]を押すと・・・ITEMでソートされて、合計金額は表示されません。
2.[ORD_IDXでソート]を押すと・・・再度、合計金額が表示されます。
3.フィルター[ON]を押すと・・・合計金額が表示されません。
しかしここで、次のレコードに移動させるとフィルター処理前の合計金額が
表示されています。
4.ここで[ITEMでソート]を押すと・・・合計金額は表示されません。
5.驚いて[ORD_IDX]を押すと・・・合計金額は表示されません。
6.これはいけないと思い、フィルター[OFF]を押すと・・・合計金額は表示されません。
その2
1.フィルター[ON]を押すと・・・合計金額が表示されません。
しかしここで、次のレコードに移動させるとフィルター処理前の合計金額が
表示されました。
2.フィルター[OFF]を押して、合計金額が正しいことを確認します。
合計金額は正しく表示されました。
と思ったけど、フィルター処理されたレコードに移動させると、
合計金額が消えてしまいました。
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 プロパティは相互に排他的です。
// 一方を設定するともう一方はクリアされます。