2012-10-17 51 views
1

使用Delphi 2005,我有一個TwwDBGrid(InfoPower),允許用戶選擇零件數量來生成報價。部分選擇過程是允許用戶爲由DiscountAmount和DiscountType組成的每個部分添加折扣。 DiscountAmount是折扣金額,DiscountType是折扣金額類型(折扣,折扣或平價)。這些數據保存在一個名爲ClientDataSetParts的ClientDataSet中。OnCalcFields導致StackOverflow

在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')。值時,ClientDataSetPartsCalcFields被再次調用,導致無盡的調用並最終導致堆棧溢出。

如何在不遞迴調用ClientDataSetPartsCalcFields的情況下更新此值?

+0

您是否嘗試過將AutoCalcFields設置爲false? –

+0

不改變任何東西。 – BrianKE

+0

好的。但是請閱讀關於'AutoCalcFields'的文檔,或許它會提供一些見解。 –

回答

2

您正在進入的無限循環是由代碼更改值,看到它已更改並重新啓動更改(如您已知)所致。爲了解決這個問題,在過程開始時,將OnCalc事件設置爲零,然後在最後重新設置該過程。這樣,事件監視將在實際處理期間暫停,然後在處理完成後恢復並分配新值。

+3

這可能會掩蓋潛在的錯誤並導致其他錯誤。 –

+0

謝謝湯姆,那工作。 – BrianKE

+0

@David Heffernan - 你能詳細說明嗎?我不明白它會如何破壞任何東西,而且在過去,我根據自己的消息來源(書籍,互聯網搜索和高級同事)使用此解決方案作爲「正確」解決方案。 –

2

此行爲是您修改非計算字段時發生的情況。 OnCalcFields事件不應對非計算字段進行任何修改。

我對數據庫結構一無所知,但如果我的預感是正確的,那麼您正在修改OnCalcFields事件處理程序中的某個非計算字段。而且,由於您修改了非計算字段,因此需要重新計算計算的字段。因此調用OnCalcFields。其中修改了非計算字段。而且,好吧,你可以看到這是怎麼回事!

+0

字段DiscountDollarAmount是fkCalculated類型。我的操作說明解釋了我在做什麼,以TotalPrice並應用折扣。我如何做到這一點,使我不會遇到這種遞歸,而不使用@Tom建議的方法? – BrianKE

+1

好的,顯然你正在做別的事情。在啓用了Debug DCU的情況下使用調試器,並在首次遞歸調用OnCalcFields時查看調用堆棧。查看調用堆棧中的線索,瞭解爲什麼頂級'OnCalcFields'引發對'OnCalcFields'的遞歸調用。如果可能,請向我們顯示該調用堆棧。 –

+0

所以我通過@Tom的建議得到了一切。然後我註釋掉了兩行關閉,然後再打開OnCalcFields方法,一切都按預期工作。無法解釋爲什麼昨天我遇到了無限循環,今天我並不是唯一的改變就是從這兩行中脫穎而出。無論如何,感謝大家的幫助。 – BrianKE

相關問題