如何讓dbgrid內某欄位對dbgrid內的欄位做運算? |
答題得分者是:kevin2004
|
monkeyhung
一般會員 發表:51 回覆:55 積分:21 註冊:2006-12-16 發送簡訊給我 |
|
bruce
中階會員 發表:19 回覆:121 積分:83 註冊:2002-04-16 發送簡訊給我 |
|
monkeyhung
一般會員 發表:51 回覆:55 積分:21 註冊:2006-12-16 發送簡訊給我 |
|
kevin2004
資深會員 發表:18 回覆:463 積分:416 註冊:2005-05-29 發送簡訊給我 |
用計算欄位是蠻方便省事的,但有時如果要作更強大的管理與控制時,可能換用別的DBGrid-Even可能更易發揮。比如在你現在這個讓User直接以DBGrid作異動介面﹝最難控制可是也是最直覺及被客戶接受的方式﹞,你可以用DBGrid.OnColExit與DBgridOnColEnter作檢篩發動計算的點,可能更好用及功能更可自己操控與更強大萬倍。檢核的例子如在DBGridOnColExit時先判斷User是離開單價或數量的欄位時,先檢核是否已輸入計算必須的欄位及合理值,再進行計算。靈活與強大是指,你可以作適時適點與較複雜的HInt等,或可啟動SQL到後端別的表中抓必須的資料﹝你的例子中是同表,沒這個須求﹞等。
CalcField受人控制,蠻讓人不舒服。Delphi啟動DataSet.OnCalcFieldS-Even就是有限定的那五種情況,如果夠用還好﹝不過,在你現在這個問題的情況是夠用的﹞,如果不是就討厭了。而且,CalcField通常會是VirtualField這在某些情況會給你大苦頭吃的。還是以少用為宜。
------
Kevin |
kevin2004
資深會員 發表:18 回覆:463 積分:416 註冊:2005-05-29 發送簡訊給我 |
========================== 引用來文==========================
在輸入完 數量 單價 折扣 時小計的欄位會自動將 (數量*單價-折扣)後的值,顯示在小計這個欄位。而user若在數量、單價、折扣任何一個欄位在更改時,小計也會自動在重新計算 ========================== 引用來文========================== ==>用DBgridOnColExit,如 begin if Not ( AddMode or EditMode ) then exit ; if (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName , 'Quant')=0 ) or (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName , 'UnitPrice')=0 ) or ... () then begin ....檢核單價、數量、預定折數、定單編號等必要欄位等是否已輸入及是否在合理範圍 ....如否,ShowMessage,如是計算及填入TotalPrice欄位中 exit ; end ; ========================== 引用來文========================== 而我最後想當user在dbgrid內輸入一筆資料後或是多筆,都會自動將小計欄位內的值丟給 未稅金額dbedit內 ========================== 引用來文========================== ==>作以上作業時同時將此值給定給同DataSet.FieldByName('未稅金額')。只要此欄有值,自然在其DBEdit中就會馬上DataAware顯示出來了。
------
Kevin |
kevin2004
資深會員 發表:18 回覆:463 積分:416 註冊:2005-05-29 發送簡訊給我 |
|
monkeyhung
一般會員 發表:51 回覆:55 積分:21 註冊:2006-12-16 發送簡訊給我 |
大大我有點看不太種紅色的部份,可以請你教導一下嗎
還一點就是,大大我的dbedit是別個table的,和圖片的那個不是同一個table的 我目前是有做到,已經可以把(數量*單價-折扣)後的值丟給dbedit了,因為我的dbgrid是及時存入db裡的 而我是在當小計欄位有值時就會把值丟給dbedit了,而我現在就想把dbgrid小計所丟給dbedit的值都能加總起來而再顯現在dbedit dbgrid是單身檔 而dbedit是單頭檔裡的未稅金額欄位,二個table有相關連的欄位 不知大大看得懂嗎 就是當dbgrid 輸入筆資料時, 數量 單價 折扣 小計 另一個table的dbedit 第一筆 10 2 2 18 18 第二筆 20 2 10 30 48 第三筆 50 2 100 148 這就是我要的目的 ===================引 用 kevin2004 文 章=================== ========================== 引用來文========================== 在輸入完? 數量?? 單價? 折扣 時小計的欄位會自動將? (數量*單價-折扣)後的值,顯示在小計這個欄位。而user若在數量、單價、折扣任何一個欄位在更改時,小計也會自動在重新計算 ========================== 引用來文========================== ??? ==>用DBgridOnColExit,如 ??? begin ??? if Not ( AddMode or EditMode ) then ??????? exit ; ??? if (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName , ??????????????????? 'Quant')=0 ) or? ??????? (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName , ??????????????????? 'UnitPrice')=0 ) or?... () then ??????? begin ??????? ....檢核單價、數量、預定折數、定單編號等必要欄位等是否已輸入及是否在合理範圍 ??????? ....如否,ShowMessage,如是計算及填入TotalPrice欄位中 ??????? exit ;? ??????? end ;? ========================== 引用來文========================== 而我最後想當user在dbgrid內輸入一筆資料後或是多筆,都會自動將小計欄位內的值丟給? 未稅金額dbedit內 ========================== 引用來文========================== ??? ==>作以上作業時同時將此值給定給同DataSet.FieldByName('未稅金額')。只要此欄有值,自然在其DBEdit中就會馬上DataAware顯示出來了。 |
kevin2004
資深會員 發表:18 回覆:463 積分:416 註冊:2005-05-29 發送簡訊給我 |
紅色的部份
if (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName ,'Quant')=0) then ==>因DBGridOnCellExit時要指定是離開那個欄位,如此才好寫適檔之處理程式碼 ==>AnsiCompareText是比對字串內容時不分大小寫,此即比對欄位名稱 ==>(Sender as TDBGrid).SelectedField.FieldName 會抓取啟動此碼的Cell對應的Fieldname ==>Quant是小弟假設此『數量』之欄位名稱
------
Kevin |
kevin2004
資深會員 發表:18 回覆:463 積分:416 註冊:2005-05-29 發送簡訊給我 |
已經可以把(數量*單價-折扣)後的值丟給dbedit了,因為我的dbgrid是及時存入db裡的
dbgrid是單身檔 而dbedit是單頭檔裡的未稅金額欄位,二個table有相關連的欄位 =======================引用來文============================ 問題出在那裏及你要的是什麼。假設你只是要當 User在DBGrid中輸入了某些必要的欄位後進行計算﹝這可以用CalcField或我講的DBGridOnColExit作﹞後丟給同表的小計欄,這沒問題。要丟給另一表的某欄,這也沒問題阿?因為你不是已將兩表都同時Open了嗎?在DBGridOnColExit時只要判斷是退出標的欄時作檢核、對同表小計計算給值、及給值給另一表,就可以了。你要問的是這個嗎?
------
Kevin |
kevin2004
資深會員 發表:18 回覆:463 積分:416 註冊:2005-05-29 發送簡訊給我 |
已經可以把(數量*單價-折扣)後的值丟給dbedit了,因為我的dbgrid是及時存入db裡的
=======================引用來文============================ 這與是否有先存入db沒關係,即使你是用BatchUpdateMode,這也可以作到的。當然如果有MasterDetail或甚至多層MasterDetail會有點麻煩,不過都不是大問題。都可以作到的。沒必要先存入db。 我看過你起的另一個用TField.OnValidEven的問題,我覺得你可能已把自己陷入一個本來怖必要的漩渦了。有很多人很喜歡用OnValidEven,不過在你的環境中,這是不適宜的。李維講的不一定對的。 你把涉及資料完整性須用交易保護的多檔異動分別存檔,且用到一個很可怕的DBGrid輸入界面,你的架構絕對會讓你費大功夫吃大苦頭的。 問題會很多的。
------
Kevin |
monkeyhung
一般會員 發表:51 回覆:55 積分:21 註冊:2006-12-16 發送簡訊給我 |
kevin2004大大謝謝你這樣幸苦為我解答,真的很感謝你 後來我改用你的方法,當user在輸入完單價或是折扣時,已可以把小計自動算出來了 因為我這樣寫的話,只能把當筆的小計計算出來,而不會累加到上筆的金額,我最後的目的就是想當user在輸入第二筆時,在輸入完折扣 後,小計那欄是出現4500,而不是2700,同樣的第三筆、第四筆....之後的也是如此,不知如何能達到呢 希望大大能提醒一下笨笨的小弟 procedure TFPUR220.DBGrid_PUR200DColExit(Sender: TObject); begin inherited; if not (Query_PUR200D.State = dsInsert) or (Query_PUR200D.State = dsEdit) then exit ; if (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName ,'PriceU')=0 ) or (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName ,'Discount')=0 ) then begin Query_PUR200D.FieldByName('SubTot').AsInteger :=(Query_PUR200D.FieldByName('Qty').AsInteger * Query_PUR200D.FieldByName('PriceU').AsInteger - Query_PUR200D.FieldByName('Discount').AsInteger); end; end;
編輯記錄
monkeyhung 重新編輯於 2007-05-10 13:44:58, 註解 無‧
|
kevin2004
資深會員 發表:18 回覆:463 積分:416 註冊:2005-05-29 發送簡訊給我 |
我瞭解你的意思了。
你這個DBGrid裏存的應該是同一張訂單明細的資料,即你這個應該是個『訂單』Master檔---『訂單明細』Detail檔。那這是合理的作法,用DBGrid也是合理的。 這個累積的金額應該是整張訂單的總價款,這個數值可能不要放在這個Detail檔的DBGrid中,而放在Master訂單檔的欄位較好。 如果是這樣,你還是照樣,在此DBGridOnColExit以單價X數量-折扣==> 存入此筆小計。此時別急者結束這段碼,在 exit前下個命令要Delphi掃瞄你的Detail表,將此訂單的各小計累加給master的總價款就好了。 這應該沒問題。 此時要注意的是,如果你有作BatchUpdate的話,你要多加小心。因為你是用Master-Detail作,當你算完Detail多筆異動,又對Master下MasterAdoQuery.Edit,小心Delphi會將你已修改但未存檔的Detail丟光光,這時要如何作?我要想想。 剛剛才抓了三四個小時帳,頭昏眼花。先要讓大腦休息一下。 公司好幾年前有因客戶堅持下寫過一個結合六七個檔但純用DBGrid作輸入界面的模組,光是這支Form就寫了好幾萬行......
------
Kevin
編輯記錄
kevin2004 重新編輯於 2007-05-10 23:26:17, 註解 無‧
|
monkeyhung
一般會員 發表:51 回覆:55 積分:21 註冊:2006-12-16 發送簡訊給我 |
大大真的勵害呀,一眼就看出的做法
若是我再多下這一段的話,可以這樣嗎 DM1.SQL_Command := 'select sum(SubTot) from PUR200D where PONo="' Query_PUR200DPONo.Text '" '; DM1._Query_table(DM1.Qtmp,DM1.SQL_Command); Query_PUR200DSubTot.Text := Query_PUR200D.FieldByName('SubTot').AsString; 因為我的DBGrid是採用每輸入完一筆細項就馬上寫入DB裡的方式。 但有朋友跟我說,因為我是DB是採用SQL Sever 2005的,若是下這樣的SQL語法可以 嗎select sum(SubTot) from PUR200D where PONo 還是說我要用 while not Query_PUR200D.DBGrid //不太會寫這一段 的方式呢? 還有一點就是,為何我在---『訂單明細』Detail檔做新增的動作時,每要新增一筆都是會在第一列的地方輸入 而不是說在DBGrid的最後列耶,這樣會影響到我寫while not Query_PUR200D.DBGrid 時的動作嗎? 大大你這句 如果你有作BatchUpdate的話 是指cachedUpdate設為True嗎,若是的話,我有這樣做 再次謝謝大大你下班後還這麼幸苦為我解答^^ ===================引 用 kevin2004 文 章=================== 我瞭解你的意思了。 你這個DBGrid裏存的應該是同一張訂單明細的資料,即你這個應該是個『訂單』Master檔---『訂單明細』Detail檔。那這是合理的作法,用DBGrid也是合理的。 這個累積的金額應該是整張訂單的總價款,這個數值可能不要放在這個Detail檔的DBGrid中,而放在Master訂單檔的欄位較好。 如果是這樣,你還是照樣,在此DBGridOnColExit以單價X數量-折扣==> 存入此筆小計。此時別急者結束這段碼,在 exit前下個命令要Delphi掃瞄你的Detail表,將此訂單的各小計累加給master的總價款就好了。 這應該沒問題。 此時要注意的是,如果你有作BatchUpdate的話,你要多加小心。因為你是用Master-Detail作,當你算完Detail多筆異動,又對Master下MasterAdoQuery.Edit,小心Delphi會將你已修改但未存檔的Detail丟光光,這時要如何作?我要想想。 剛剛才抓了三四個小時帳,頭昏眼花。先要讓大腦休息一下。 公司好幾年前有因客戶堅持下寫過一個結合六七個檔但純用DBGrid作輸入界面的模組,光是這支Form就寫了好幾萬行...... |
kevin2004
資深會員 發表:18 回覆:463 積分:416 註冊:2005-05-29 發送簡訊給我 |
因為我的DBGrid是採用每輸入完一筆細項就馬上寫入DB裡的方式。
如果你有作BatchUpdate的話 是指cachedUpdate設為True嗎,若是的話,我有這樣做 =====================引用來文=============== ==>有好長一段時間沒用BDE-Query,剛才翻了老半天OnLineHelp,實在急就章不得。 ==>只能講講原則,批次更新意指『不馬上寫入DB,及一次寫入多筆異動』,減少DB執行Transaction的次數以加快速度。 ==>而且在個Form裏如果你有開兩個檔﹝Master訂單主體及Detail明細多筆﹞,這最好要用批次更新及用交易保護起來,而且所有作業都要在你控制之下。不然系統裏可能會留下很多孤兒資料及失敗的垃圾,這是很嚴重的問題的。 ==>我有看過你試者用TField.OnValidEven來解過。很多人很喜歡用OnValidEven,可是它是放在DataModule的某個DataSet的TField中,即它應該是個只要DataAware元件.DataSource接的是這個DataSet就會啟動這個Even,此在要作應地制宜的動作及強調要完全控制的環境就心餘力拙了。
------
Kevin |
kevin2004
資深會員 發表:18 回覆:463 積分:416 註冊:2005-05-29 發送簡訊給我 |
==>用批次更新及交易的架構
==>搭配一個Function及在DBGrid1OnColExit中 procedure TForm1.StatThisOrder ... var S : integer ; begin // 記得啟動Detail異動作業前要先下MasterQuery.Edit,而不可在 // DetailQuery每筆計算統計時下MasterQuery.Edit,否則會將 // DetailQuery的異動丟掉了 DetailQuery.FIrst ; S := 0 ; while Not DetailQuery.eof do begin if ot DetailQuerySumOfThisRecord.IsNull then begin S := S DetailQuerySumOfThisRecord.value ; end ; DetailQuery.Next ; end ; MasterQueryThisOrderTotal.Value := S ; end ; procedure TForm1.DBGrid1ColExit(Sender: TObject); var FoundIt : Boolean ; TempI : integer ; begin if Not ( AddMode or EditMode ) then exit ; if AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName ,'數量/單價/折扣/...')=0 then begin 作此筆計算 StatThisOrder ... exit ; end ; 其他欄位或其他之處理 end ; ==>再用個WriteBitBtn作整體查核及執行批次存檔與交易整體存入資料庫或拉回 ==>當然有些查核可能要分散在各元件中﹝在此即你的DBGrid各Even中〕,以加快對User的反應速度
------
Kevin |
kevin2004
資深會員 發表:18 回覆:463 積分:416 註冊:2005-05-29 發送簡訊給我 |
為何我在---『訂單明細』Detail檔做新增的動作時,每要新增一筆都是會在第一列的地方輸入
而不是說在DBGrid的最後列耶,這樣會影響到我寫while not Query_PUR200D.DBGrid 時的動作嗎? ==>不會影響,只是會與User的直覺抵觸,會惹火User而矣。一般的感覺,新增應該出現在DBGrid的最下一列 ==>通常會將DBGrid的新增鎖死,要User要新增一項定單明細一定在某一ColExit時才會啟動DetailQuery.Append,及在此時改與必要欄位的值,如定單編號及明細項編號等。 ==>如果是批次更新,因此明細號尚未存入資料庫,要注意處理 ==>DBGrid是很麻煩的異動界面 ==>要上班了
------
Kevin |
monkeyhung
一般會員 發表:51 回覆:55 積分:21 註冊:2006-12-16 發送簡訊給我 |
大大我現在把它改成以下這樣的寫法了,但是為什麼我在輸入完單價後就會一直出現Showmessage('請確認明細表是否已填畢');這個訊息呀
而且是在我加入下列紅色的部份才會這樣的耶,怎會這樣呢???一直想不通 procedure TFPUR220.Query_PUR200DBeforePost(DataSet: TDataSet); var xProdNo : string; begin inherited; if (Query_PUR200D.FieldByName('PONo').Text = '') and (Query_PUR200D.FieldByName('InDay').Text = '') and (Query_PUR200D.FieldByName('UsrNo').Text = '') then begin if (DataSet.FieldByName('Seq').AsString = '') or (DataSet.FieldByName('ProdNo').AsString = '') or (DataSet.FieldByName('Qty').AsString = '') or (DataSet.FieldByName('UnitP').AsString = '') or (DataSet.FieldByName('PriceU').AsString = '') or (DataSet.FieldByName('ShipDay').AsString = '') then begin Showmessage('請確認明細表是否已填畢'); Abort; end; xProdNo := Query_PUR200D.fieldbyname('ProdNo').AsString; Dm1.SQL_Command := 'Select * from PUR200D where PONO=''' DBEditNo.Text ''''; Dm1._Query_table(Dm1.Qtmp,Dm1.SQL_Command); DM1.Qtmp.Open; DM1.Qtmp.First; while not DM1.Qtmp.Eof do begin if (xProdNo=DM1.Qtmp.FieldByName('ProdNo').AsString) then begin showmessage('此筆序號或品項已存在,請確認!'); Abort; end; DM1.Qtmp.Next; end; Query_PUR200D.FieldByName('PONo').Text := DBEditNo.Text; Query_PUR200D.FieldByName('InDay').Text := DBEdit_InDay.Text; Query_PUR200D.FieldByName('UsrNo').Text := DBEdit_UsrNo.Text; end; end; procedure TFPUR220.DBGrid_PUR200DColExit(Sender: TObject); begin inherited; if not (Query_PUR200D.State = dsInsert) or (Query_PUR200D.State = dsEdit) then exit ; if (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName ,'PriceU')=0 ) or //我自已是在猜想會是因為這裡的因素嗎? (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName ,'Discount')=0 ) then begin Query_PUR200D.FieldByName('SubTot').AsInteger :=(Query_PUR200D.FieldByName('Qty').AsInteger * Query_PUR200D.FieldByName('PriceU').AsInteger - Query_PUR200D.FieldByName('Discount').AsInteger); CalTot; end; end; procedure TFPUR220.CalTot; var xTot:real; begin xTot :=0; Query_PUR200D.first; while not Query_PUR200D.eof do begin xTot := xTot Query_PUR200D.fieldbyname('SubTot').asfloat; Query_PUR200D.next; end; Query_PUR200M.FieldByName('Subtot').asString:= floattostrf(xTot,ffFixed,10,0); end; |
T.J.B
版主 發表:29 回覆:532 積分:497 註冊:2002-08-14 發送簡訊給我 |
===================引 用 monkeyhung 文 章=================== 大大我現在把它改成以下這樣的寫法了,但是為什麼我在輸入完單價後就會一直出現Showmessage('請確認明細表是否已填畢');這個訊息呀 而且是在我加入下列紅色的部份才會這樣的耶,怎會這樣呢???一直想不通 procedure TFPUR220.Query_PUR200DBeforePost(DataSet: TDataSet); var xProdNo : string; begin ? inherited; ? if (Query_PUR200D.FieldByName('PONo').Text = '') and (Query_PUR200D.FieldByName('InDay').Text = '') ? and (Query_PUR200D.FieldByName('UsrNo').Text = '') then ? begin ?if (DataSet.FieldByName('Seq').AsString = '') or (DataSet.FieldByName('ProdNo').AsString = '') ? or (DataSet.FieldByName('Qty').AsString = '') or (DataSet.FieldByName('UnitP').AsString = '') ?? or (DataSet.FieldByName('PriceU').AsString = '') or (DataSet.FieldByName('ShipDay').AsString = '') ?? then ????? begin ??????????? Showmessage('請確認明細表是否已填畢'); ??????????? Abort; ????? end; ??? xProdNo := Query_PUR200D.fieldbyname('ProdNo').AsString; ??? Dm1.SQL_Command := 'Select * from PUR200D where PONO=''' DBEditNo.Text ''''; ??? Dm1._Query_table(Dm1.Qtmp,Dm1.SQL_Command); ??? DM1.Qtmp.Open; ??? DM1.Qtmp.First; ??? while not DM1.Qtmp.Eof do ??? begin ???????? if (xProdNo=DM1.Qtmp.FieldByName('ProdNo').AsString)? then ??????????? begin ???????????????? showmessage('此筆序號或品項已存在,請確認!'); ???????????????? Abort; ??????????? end; ???????? DM1.Qtmp.Next; ??? end; ??? ?????? Query_PUR200D.FieldByName('PONo').Text := DBEditNo.Text; ?????? Query_PUR200D.FieldByName('InDay').Text := DBEdit_InDay.Text; ?????? Query_PUR200D.FieldByName('UsrNo').Text := DBEdit_UsrNo.Text; ??? end; end; procedure TFPUR220.DBGrid_PUR200DColExit(Sender: TObject); begin ? inherited; ???? if not? (Query_PUR200D.State = dsInsert) or (Query_PUR200D.State = dsEdit) then ??????? exit ; ??? if (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName ,'PriceU')=0 ) or?? //我自已是在猜想會是因為這裡的因素嗎? ??????? (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName ,'Discount')=0 )? then ??????? begin ?????? Query_PUR200D.FieldByName('SubTot').AsInteger :=(Query_PUR200D.FieldByName('Qty').AsInteger ?????? * Query_PUR200D.FieldByName('PriceU').AsInteger - Query_PUR200D.FieldByName('Discount').AsInteger); ??????? CalTot; ????? end; end; procedure TFPUR220.CalTot; var xTot:real; begin ? xTot :=0; ? Query_PUR200D.first; ? while not Query_PUR200D.eof do begin ???? xTot := xTot Query_PUR200D.fieldbyname('SubTot').asfloat; ???? Query_PUR200D.next; ? end; ? Query_PUR200M.FieldByName('Subtot').asString:= floattostrf(xTot,ffFixed,10,0); ? end; 單純由你的程式碼來看 是因為下面這幾個欄位只要其中一個沒有填值就會觸發訊息 檢查看看是否有漏掉 跟你猜想的因素沒有關係 ^^ if (DataSet.FieldByName('Seq').AsString = '') or (DataSet.FieldByName('ProdNo').AsString = '') or (DataSet.FieldByName('Qty').AsString = '') or (DataSet.FieldByName('UnitP').AsString = '') or (DataSet.FieldByName('PriceU').AsString = '') or (DataSet.FieldByName('ShipDay').AsString = '')
------
天行健 君子當自強不息~~@.@ |
monkeyhung
一般會員 發表:51 回覆:55 積分:21 註冊:2006-12-16 發送簡訊給我 |
大大不是這樣子耶,我那幾行主要是讓那些欄位不能為空,但我現在只要在DBGrid裡新增一筆資料,當填完「單價」時而要再往下
填「折扣」、「預定交貨日」的,就不會讓我填了,而一直出現 Showmessage('請確認明細表是否已填畢')。對話框出來 本來若沒有加上紅色那幾行的話,一切就是ok的!! ps若是我把 if (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName ,'PriceU')=0 ) or (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName ,'Discount')=0 ) then 改成這樣的話 if (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName ,'Discount')=0 ) then 就會變成在輸入完「折扣」完後,才會出現Showmessage('請確認明細表是否已填畢')耶 我也一直找不出問題點出在那 |
T.J.B
版主 發表:29 回覆:532 積分:497 註冊:2002-08-14 發送簡訊給我 |
===================引 用 monkeyhung 文 章=================== 大大我現在把它改成以下這樣的寫法了,但是為什麼我在輸入完單價後就會一直出現Showmessage('請確認明細表是否已填畢');這個訊息呀 而且是在我加入下列紅色的部份才會這樣的耶,怎會這樣呢???一直想不通 procedure TFPUR220.Query_PUR200DBeforePost(DataSet: TDataSet); var xProdNo : string; begin ? inherited; ? if (Query_PUR200D.FieldByName('PONo').Text = '') and (Query_PUR200D.FieldByName('InDay').Text = '') ? and (Query_PUR200D.FieldByName('UsrNo').Text = '') then ? begin ?if (DataSet.FieldByName('Seq').AsString = '') or (DataSet.FieldByName('ProdNo').AsString = '') ? or (DataSet.FieldByName('Qty').AsString = '') or (DataSet.FieldByName('UnitP').AsString = '') ?? or (DataSet.FieldByName('PriceU').AsString = '') or (DataSet.FieldByName('ShipDay').AsString = '') ?? then ????? begin ??????????? Showmessage('請確認明細表是否已填畢'); ??????????? Abort; ????? end; ??? xProdNo := Query_PUR200D.fieldbyname('ProdNo').AsString; ??? Dm1.SQL_Command := 'Select * from PUR200D where PONO=''' DBEditNo.Text ''''; ??? Dm1._Query_table(Dm1.Qtmp,Dm1.SQL_Command); ??? DM1.Qtmp.Open; ??? DM1.Qtmp.First; ??? while not DM1.Qtmp.Eof do ??? begin ???????? if (xProdNo=DM1.Qtmp.FieldByName('ProdNo').AsString)? then ??????????? begin ???????????????? showmessage('此筆序號或品項已存在,請確認!'); ???????????????? Abort; ??????????? end; ???????? DM1.Qtmp.Next; ??? end; ??? ?????? Query_PUR200D.FieldByName('PONo').Text := DBEditNo.Text; ?????? Query_PUR200D.FieldByName('InDay').Text := DBEdit_InDay.Text; ?????? Query_PUR200D.FieldByName('UsrNo').Text := DBEdit_UsrNo.Text; ??? end; end; procedure TFPUR220.DBGrid_PUR200DColExit(Sender: TObject); begin ? inherited; ???? if not? (Query_PUR200D.State = dsInsert) or (Query_PUR200D.State = dsEdit) then ??????? exit ; ??? if (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName ,'PriceU')=0 ) or?? //我自已是在猜想會是因為這裡的因素嗎? ??????? (AnsiCompareText((Sender as TDBGrid).SelectedField.FieldName ,'Discount')=0 )? then ??????? begin ?????? Query_PUR200D.FieldByName('SubTot').AsInteger :=(Query_PUR200D.FieldByName('Qty').AsInteger ?????? * Query_PUR200D.FieldByName('PriceU').AsInteger - Query_PUR200D.FieldByName('Discount').AsInteger); ??????? CalTot; ????? end; end; procedure TFPUR220.CalTot; var xTot:real; begin ? xTot :=0; ? Query_PUR200D.first; ? while not Query_PUR200D.eof do begin ???? xTot := xTot Query_PUR200D.fieldbyname('SubTot').asfloat; ???? Query_PUR200D.next; ? end; ? Query_PUR200M.FieldByName('Subtot').asString:= floattostrf(xTot,ffFixed,10,0); ? end; 單純由你的程式碼來看 是因為下面這幾個欄位只要其中一個沒有填值就會觸發訊息 檢查看看是否有漏掉 跟你猜想的因素沒有關係 ^^ if (DataSet.FieldByName('Seq').AsString = '') or (DataSet.FieldByName('ProdNo').AsString = '') or (DataSet.FieldByName('Qty').AsString = '') or (DataSet.FieldByName('UnitP').AsString = '') or (DataSet.FieldByName('PriceU').AsString = '') or (DataSet.FieldByName('ShipDay').AsString = '') 麻煩版主刪掉這一篇文 不小心重覆發文 抱歉 ^^"""
------
天行健 君子當自強不息~~@.@
編輯記錄
T.J.B 重新編輯於 2007-05-14 15:54:28, 註解 無‧
|
kevin2004
資深會員 發表:18 回覆:463 積分:416 註冊:2005-05-29 發送簡訊給我 |
在我加入下列紅色的部份才會這樣的耶,怎會這樣呢???一直想不通
==>我不太敢明確的說,試推導如下: ==>假設1.你的User在DBGrid中以Enter啟動的輸入方向是橫向。此時因未離 開本筆記錄,所以未啟動存檔程序,即你的DataSetBeforePost應不該被 啟動。但它實際上是被啟動了,即你看到了你講的ShowMessage... ==>可能會如此的原因是:你是在DBGrid1OnColExit時執行本Form的proc-CalTot的 Query_PUR200M.FieldByName('Subtot').asString:= floattostrf(xTot,ffFixed,10,0); 所啟動。﹝不過沒下Post,應該不會被啟動?為何?,我就不知道了﹞ ==>因為你是水平輸入,即未啟動存檔程序,所以即使你已輸入Seq/Qty/ProdNo/...等, 可是實際上後端DB並沒收到這幾個值,所以Delphi攔截這幾個空欄值的碼還是攔下 你的程式 // 不過這邊,你好像並沒有告訴大家,你是否已有輸入好這幾個必要的欄位內容 // 自己看看,都看不懂自己在寫什麼 。可是這幾天忙者寫新案子的規劃書,實在是 // 找不出時間來試試。這點就請包涵了。
------
Kevin
編輯記錄
kevin2004 重新編輯於 2007-05-15 15:10:33, 註解 無‧
|
kevin2004
資深會員 發表:18 回覆:463 積分:416 註冊:2005-05-29 發送簡訊給我 |
其實你的問題不是很難解,不過你倒是真的選了一個很難作好的環境。
如果你要選M-DBGrid D-DBGrid來作輸入的環境,你要加寫一些程式碼: 不要用BeforePost,因為它是全AP共用,無法針對某個Form或某個User或某個User-Custom作控制 不要用TFieldOnValidEven,理由同上 所有的程式碼要集中在這個Form中。 你要善用DBGrid的好幾個Even來解這題。如果你平常要寫500行,那你個模組至少要寫3000行才行。甚至光是這個form就可能寫上好幾萬行,才能把User的行為完全控制住。 還有你沒有用交易保護資料,將來光資料安全就會叫你賠上一大筆錢的。
------
Kevin |
kevin2004
資深會員 發表:18 回覆:463 積分:416 註冊:2005-05-29 發送簡訊給我 |
你要把處理流程切割:
1.Master/Detail均設為批次更新模式 1.先以DBEdit將主訂單Master處理好,再將MasterDBGrid鎖起來,以免移動User在操作中途亂移動Master位置而造成 Detail輸入的東西被丟棄了。 2.此時將訂單編號、日期、客戶編號等存入變數 3.讓User在DetailDBGrid中讓User作輸入處理。此時要多利用D-DBGridOnColExit/D-DBgridOnColEnter等Even,作計算與檢核﹝如查核那些必要欄位未輸,或輸入值不合法。及計算等﹞及新增此定單的新Item記錄。 4.此時千萬不要用DataModule.DataSet.BeforePost或OnValidEven等作處理。如果要用DBGrid,一定要完全在你的Form控制下執行。 5.以一個WriteBitBtn/CancelBitBtn啟動總檢核及交易存資料庫的動作。 祝好運了。
------
Kevin
編輯記錄
kevin2004 重新編輯於 2007-05-15 15:29:48, 註解 無‧
|
monkeyhung
一般會員 發表:51 回覆:55 積分:21 註冊:2006-12-16 發送簡訊給我 |
|
sam8832
一般會員 發表:1 回覆:1 積分:0 註冊:2008-04-25 發送簡訊給我 |
|
kevin2004
資深會員 發表:18 回覆:463 積分:416 註冊:2005-05-29 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |