Delphi 2005を使用して、ユーザーが部品と数量を選択して見積もりを生成できるTwwDBGrid(InfoPower)があります。選択プロセスの一部は、ユーザーがDiscountAmountとDiscountTypeで構成される各部分に割引を追加できるようにすることです。DiscountAmountは割引額であり、DiscountTypeは割引額のタイプ(%オフ、$オフ、または定額)です。このデータは、ClientDataSetPartsと呼ばれるClientDataSetに保持されます。
OnCalcメソッド(ClientDataSetPartsCalcFields)内に、部品コストと割引に基づいてTotalPriceを再計算する次のコードがあります。RangePricingは、価格が範囲内の数量に基づいて計算される場合に使用されます(つまり、1-100 = $ 100、101-200 = $ 150など)。
procedure TfrmCustom_Services.ClientDataSetPartsCalcFields(
DataSet: TDataSet);
begin
inherited;
// if part is selected then calculate Total
if (ClientDataSetPartsSelected.Value) then begin
// if range pricing is defined
if (ClientDataSetParts.FieldByName('RangePricing').AsBoolean) then begin
ClientDataSetParts.FieldByName('TotalPrice').Value :=
ClientDataSetParts.FieldbyName('UnitPrice').Value;
// otherwise use regular pricing
end else begin
ClientDataSetParts.FieldByName('TotalPrice').Value :=
ClientDataSetParts.FieldbyName('UnitPrice').Value *
ClientDataSetParts.FieldByName('Quantity').Value;
end;
// otherwise clear the Total
end else begin
ClientDataSetParts.FieldByName('TotalPrice').Clear;
if (ClientDataSetParts.FieldByName('Quantity').Value <> null) then
ClientDataSetParts.FieldByName('Quantity').Clear;
if (ClientDataSetParts.FieldByName('DiscountAmount').Value <> null) then
ClientDataSetParts.FieldByName('DiscountAmount').Clear;
if (ClientDataSetParts.FieldByName('DiscountType').Value <> null) then
ClientDataSetParts.FieldByName('DiscountType').Clear;
end;
// Update totals if Discount is applied
// Only recalculate if both discount value and type are applied
// otherwise will constantly get errors when switching fields
if ((ClientDataSetPartsDiscountAmount.Value > 0) and (ClientDataSetPartsDiscountType.Value <> '')) then begin
case StringToCaseSelect((ClientDataSetPartsDiscountType.Value), ['% Disc','$ Disc','Price']) of
0 :
begin
ClientDataSetParts.FieldByName('DiscountDollarAmount').Value :=
ClientDataSetParts.FieldByName('TotalPrice').Value * (ClientDataSetParts.FieldByName('DiscountAmount').Value/100);
ClientDataSetPartsTotalPrice.Value := ClientDataSetPartsTotalPrice.Value - (ClientDataSetPartsTotalPrice.Value * (ClientDataSetPartsDiscountAmount.Value/100));
end;
1 :
begin
ClientDataSetParts.FieldByName('DiscountDollarAmount').Value := ClientDataSetPartsDiscountAmount.Value;
ClientDataSetPartsTotalPrice.Value := ClientDataSetPartsTotalPrice.Value - ClientDataSetPartsDiscountAmount.Value;
end;
2 :
begin
ClientDataSetParts.FieldByName('DiscountDollarAmount').Value :=
ClientDataSetPartsTotalPrice.Value - ClientDataSetPartsDiscountAmount.Value;
ClientDataSetPartsTotalPrice.Value := ClientDataSetPartsDiscountAmount.Value;
end;
end;
end;
end;
問題は、DiscountDollarAmount(APIを介して外部ソースに戻さなければならない割引の実際の金額)を計算しようとしたときに発生します。ClientDataSetParts.FieldByName('DiscountDollarAmount')。Valueを設定するたびに、ClientDataSetPartsCalcFieldsが再度呼び出され、無限の呼び出しが発生し、最終的にスタックオーバーフローが発生します。
ClientDataSetPartsCalcFieldsを再帰的に呼び出さずに、この値を更新するにはどうすればよいですか?