onCalcFields的事件可以只觸發一次嗎? |
答題得分者是:pedro
|
lkkplayer
一般會員 發表:26 回覆:59 積分:17 註冊:2006-11-22 發送簡訊給我 |
請教各位我有一個表如下列:
SELECTED A B C D ---------------------------------------------------------------- SELECTED,A,B的資料是下SQL語法得來 C,D是我設定增加的虛擬的計算欄(New Field->Calculated)我把計算的公式都寫在onCalcFields的事件 在onCalcFields事件中,C,D欄位都是又下SQL搜尋一些表做計算 第一次觸發onCalcFields事件的時候資料顯示很快... 但是我只要有加下列程式碼 while no ADOQuery1.eof do ADOQuery1.Edit<-----這個就會觸發onCalcFields ADOQuery1.FieldByName('SELECTED').AsInteger:=1; ADOQuery1.Post ADOQuery1.next end; 每次C,D的資料又重新算過一次 這樣導致DBGrid1的資料SHOW的時候delay的很嚴重,很像當機一樣 有方法不要一直觸發onCalcFields嗎? 還是可以寫在別的事件去計算.....不過還有另外一個問題是新增的計算欄好像只能在onCalcFields使用才會出現值.... 寫在其他地方...它的值都是空白...請教各位有什麼好方法嗎?? 如果方便的話寫個小範例讓我可以參考一下...感謝大家^^; 編輯記錄
taishyang 重新編輯於 2007-07-26 13:29:12, 註解 將文章分類成[問題]‧
|
pedro
尊榮會員 發表:152 回覆:1187 積分:892 註冊:2002-06-12 發送簡訊給我 |
|
lkkplayer
一般會員 發表:26 回覆:59 積分:17 註冊:2006-11-22 發送簡訊給我 |
您好:
我之前有試過你說的方法 我設一個變數flag:integer 程式碼大略如下: flag=0; ADOQuery1.close; ADOQuery1.sql.text:='xxxxxxx'; ADOQuery1.open; ......... flag=1; while not adoquery1.eof do adoquery1.edit; adoquery1.fieldbyname('selected').asinteger:=1; adoquery1.post; adoquery1.next; end; 在adoquery1的OnCalcFields事件中 加 if flag=0 then begin 做計算欄位計算 end; 但是執行出來的結果變成那些計算欄位的值都變成空白 是我哪裡寫錯... 我用的flag應該就算是你說旗標吧!! 還是你指的旗標變數是另外的變數種類 ===================引 用 pedro756901 文 章=================== 賦值給欄位,會觸發OnCalcFields是合理的,因為需重新計算虛擬欄位 建議可用一個旗標變數 if not EventFromProg then 做計算欄位計算
編輯記錄
lkkplayer 重新編輯於 2007-07-26 13:40:02, 註解 無‧
|
pedro
尊榮會員 發表:152 回覆:1187 積分:892 註冊:2002-06-12 發送簡訊給我 |
|
dyming
初階會員 發表:0 回覆:11 積分:32 註冊:2003-04-21 發送簡訊給我 |
可將程序複雜的結果另開欄位記錄 (為加速反正規化), 寫相關的 TField.OnChange 將計算結果寫入此欄位,
因為是正式欄位, 以後取用時也方便. 要避免無謂的 OnCalcFields 事件, 您可以判斷 TField.Value 與 TField.OldValue 不同才處理, 另外, 在大量的資料移動前, DataSet 設定 AutoCalcFields = False (最好也 DisableControls), 等處理完後再將 AutoCalcFields = True 並執行一次 Edit Cancel (觸動 OnCalcFields), 若有 DisableControls 記得要 EnableControls 回來. |
lkkplayer
一般會員 發表:26 回覆:59 積分:17 註冊:2006-11-22 發送簡訊給我 |
我依照您的意思加了
flag:=1; while xxx do ........ end; flag:=0; <-加這一個不夠 adoquery1.first <- 還要觸發一次 onCalcFields事件原本被清為空白的值,才會在恢復耶!! 整體的速度快多了...基本上是要減少觸發onCalcFields事件 只是還有一個也是一樣很慢 我在DBGrid1DblClick事件中所加的程式碼 flag:=1; case ADOQuery1.FieldByName('SELECTED').AsInteger of 0 : begin //flag:=1; ADOQuery1.Edit; //flag:=1; ADOQuery1.FieldByName('SELECTED').AsInteger := 1; flag:=0; ADOQuery1.Post; end; 1 : begin //flag:=1; ADOQuery1.Edit; //flag:=1; ADOQuery1.FieldByName('SELECTED').AsInteger := 0; flag:=0; ADOQuery1.Post; end; end; 點一次過很久才會變更狀態.....因為一樣會觸發onCalcFields事件這個也沒法在改了@@; 不過還是謝謝您的指導^^" ===================引 用 pedro756901 文 章=================== 在while loop 之後 需把flag清為0吧? |
pedro
尊榮會員 發表:152 回覆:1187 積分:892 註冊:2002-06-12 發送簡訊給我 |
|
lkkplayer
一般會員 發表:26 回覆:59 積分:17 註冊:2006-11-22 發送簡訊給我 |
dyming,您好
我看了您的回答.....我並不是很懂您要我做的事情 如果方便的話可以寫個小程式讓我參考嗎?? ===================引 用 dyming 文 章=================== 可將程序複雜的結果另開欄位記錄 (為加速反正規化), 寫相關的 TField.OnChange 將計算結果寫入此欄位, 因為是正式欄位, 以後取用時也方便. 要避免無謂的 OnCalcFields 事件, 您可以判斷 TField.Value 與 TField.OldValue 不同才處理, 另外, 在大量的資料移動前, DataSet 設定 AutoCalcFields = False (最好也 DisableControls), 等處理完後再將 AutoCalcFields = True 並執行一次 Edit Cancel (觸動 OnCalcFields), 若有 DisableControls 記得要 EnableControls 回來. |
VICSYS
初階會員 發表:21 回覆:64 積分:32 註冊:2002-10-10 發送簡訊給我 |
1:以 Dataset.State 來看, 會有下列態, 會觸發 onCalcFields
dsCalcFields dsInternalCalc dsEdit dsInsert 但是您不能不去計算出該值用來顯示, 因為 CalcFields 實際上只有一筆的 Buffer 就算 dsEdit 不需要計算, 不過如果不這樣做, 您會發覺, 進入 dsEdit 時 顯示孌成空白! 只好自行把計算值保留, 再取出. 但這樣工程有點大! 2.把 ADO DatSet 改為 ClientDataSet, 利用 ClientDataSet 的 InternalCalc 的類型來解決. InternalCalc 好像記憶體欄位一樣. 用 ClientDataSet 的彈性很大, 只不過要再加上 DataSetProvider ClientDataSet -> DataSetProvider -> ADO DataSet |
lkkplayer
一般會員 發表:26 回覆:59 積分:17 註冊:2006-11-22 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |