1

Using Delphi 2005, I have a TwwDBGrid (InfoPower) that allows the user to select part(s) & quantities to generate a quote. Part of the selection process is to allow the user to add a discount for each part consisting of DiscountAmount and DiscountType. DiscountAmount is the amount of the discount and DiscountType is the type of discount amount (% off, $ off or flat price). This data is held in a ClientDataSet called ClientDataSetParts.

Within the OnCalc method (ClientDataSetPartsCalcFields) I have the following code which will recalculate the TotalPrice based on the parts cost and any discounts. RangePricing is used in the case where a price is calculated based on a quantity within a range (i.e., 1-100 = $100, 101-200 = $150, etc.):

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;

The problem comes when I try to calculate DiscountDollarAmount (the actual dollar figure of the discount that I have to return to an outside source via API). Each time I set the ClientDataSetParts.FieldByName('DiscountDollarAmount').Value, ClientDataSetPartsCalcFields is called again causing endless calls and eventually a stack overflow.

How can I update this value without calling ClientDataSetPartsCalcFields recursively?

4

2 回答 2

2

当您修改非计算字段时会发生这种行为。该OnCalcFields事件不应对非计算字段进行任何修改。

我对您的数据库结构一无所知,但如果我的预感是正确的,那么您正在修改OnCalcFields事件处理程序中某处的非计算字段。并且因为你修改了一个非计算字段,所以需要重新计算计算字段。也因此OnCalcFields被称为。这会修改非计算字段。而且,好吧,你可以看到这是怎么回事!

于 2012-10-17T18:02:02.630 回答
2

您进入的无限循环是由代码更改值,看到它已更改并重新开始更改(如您所知)引起的。为了解决这个问题,在过程开始时,将 OnCalc 事件设置为 nil,然后在结束时将其重新设置为过程。这样,事件监控将在其实际处理期间暂停,然后在处理完成并分配新值后恢复。

于 2012-10-17T15:53:03.613 回答