線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:5512
推到 Plurk!
推到 Facebook!

如何讓dbgrid內某欄位對dbgrid內的欄位做運算?

答題得分者是:kevin2004
monkeyhung
一般會員


發表:51
回覆:55
積分:21
註冊:2006-12-16

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-05-03 09:32:25 IP:203.69.xxx.xxx 訂閱

各位大大想請教一下

我可以做到說當user在輸入完 數量 單價 折扣 時

小計的欄位會自動將 (數量*單價-折扣)後的值,顯示在小計這個欄位

而user若在數量、單價、折扣任何一個欄位在更改時,小計也會自動在重新計算

而我最後想當user在dbgrid內輸入一筆資料後或是多筆,都會自動將小計欄位內的值丟給 未稅金額dbedit內

bruce
中階會員


發表:19
回覆:121
積分:83
註冊:2002-04-16

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-05-04 16:27:53 IP:203.70.xxx.xxx 訂閱
請將小計設定為【計算欄位】即可。
monkeyhung
一般會員


發表:51
回覆:55
積分:21
註冊:2006-12-16

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-05-05 13:04:59 IP:59.114.xxx.xxx 訂閱
恩~~我現在是分別在user輸入完單價與折扣時都會觸發一次運算,而把值帶給小計
而我若想把dbgrid內所有得知的的小計,再做一計加總,再把得到的總計,丟給dbedit裡不知要用何種方法呢
希望各大大提點一下小弟~~
===================引 用 bruce 文 章===================
請將小計設定為【計算欄位】即可。
kevin2004
資深會員


發表:18
回覆:463
積分:416
註冊:2005-05-29

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-05-05 16:50:18 IP:61.219.xxx.xxx 訂閱
用計算欄位是蠻方便省事的,但有時如果要作更強大的管理與控制時,可能換用別的DBGrid-Even可能更易發揮。比如在你現在這個讓User直接以DBGrid作異動介面﹝最難控制可是也是最直覺及被客戶接受的方式﹞,你可以用DBGrid.OnColExit與DBgridOnColEnter作檢篩發動計算的點,可能更好用及功能更可自己操控與更強大萬倍。檢核的例子如在DBGridOnColExit時先判斷User是離開單價或數量的欄位時,先檢核是否已輸入計算必須的欄位及合理值,再進行計算。靈活與強大是指,你可以作適時適點與較複雜的HInt等,或可啟動SQL到後端別的表中抓必須的資料﹝你的例子中是同表,沒這個須求﹞等。
CalcField受人控制,蠻讓人不舒服。Delphi啟動DataSet.OnCalcFieldS-Even就是有限定的那五種情況,如果夠用還好﹝不過,在你現在這個問題的情況是夠用的﹞,如果不是就討厭了。而且,CalcField通常會是VirtualField這在某些情況會給你大苦頭吃的。還是以少用為宜。
------
Kevin
編輯記錄
kevin2004 重新編輯於 2007-05-05 17:09:46, 註解 無‧
kevin2004 重新編輯於 2007-05-05 17:10:27, 註解 無‧
kevin2004
資深會員


發表:18
回覆:463
積分:416
註冊:2005-05-29

發送簡訊給我
#5 引用回覆 回覆 發表時間:2007-05-05 17:01:20 IP:61.219.xxx.xxx 訂閱
========================== 引用來文==========================
在輸入完 數量 單價 折扣 時小計的欄位會自動將 (數量*單價-折扣)後的值,顯示在小計這個欄位。而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

發送簡訊給我
#6 引用回覆 回覆 發表時間:2007-05-05 17:08:48 IP:61.219.xxx.xxx 訂閱
以上作業還要搭配一個技巧,通常User喜歡用Enter作輸入換欄的控制,所以你要讓User設定現在Enter表DBGrid水平移位或垂直移位的控制才行。

DBGrid作輸入界面實在因太靈活致完全不受你的控制,實在是很不理想的輸入界面。我通常會寫成單筆異動,可是也搭配批次讓User在DBGrid某些限定的欄位移動與編修的功能。
盡可能不要讓User直接以DBGrid作異動界面,實在是對資料完整性是一大威脅。
------
Kevin
monkeyhung
一般會員


發表:51
回覆:55
積分:21
註冊:2006-12-16

發送簡訊給我
#7 引用回覆 回覆 發表時間:2007-05-05 17:20:01 IP:59.114.xxx.xxx 訂閱
大大我有點看不太種紅色的部份,可以請你教導一下嗎
還一點就是,大大我的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

發送簡訊給我
#8 引用回覆 回覆 發表時間:2007-05-07 21:05:43 IP:61.219.xxx.xxx 訂閱
紅色的部份
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

發送簡訊給我
#9 引用回覆 回覆 發表時間:2007-05-07 21:22:27 IP:61.219.xxx.xxx 訂閱
已經可以把(數量*單價-折扣)後的值丟給dbedit了,因為我的dbgrid是及時存入db裡的
dbgrid是單身檔 而dbedit是單頭檔裡的未稅金額欄位,二個table有相關連的欄位
=======================引用來文============================

問題出在那裏及你要的是什麼。假設你只是要當 User在DBGrid中輸入了某些必要的欄位後進行計算﹝這可以用CalcField或我講的DBGridOnColExit作﹞後丟給同表的小計欄,這沒問題。要丟給另一表的某欄,這也沒問題阿?因為你不是已將兩表都同時Open了嗎?在DBGridOnColExit時只要判斷是退出標的欄時作檢核、對同表小計計算給值、及給值給另一表,就可以了。你要問的是這個嗎?

------
Kevin
kevin2004
資深會員


發表:18
回覆:463
積分:416
註冊:2005-05-29

發送簡訊給我
#10 引用回覆 回覆 發表時間:2007-05-07 21:31:01 IP:61.219.xxx.xxx 訂閱
已經可以把(數量*單價-折扣)後的值丟給dbedit了,因為我的dbgrid是及時存入db裡的

=======================引用來文============================
這與是否有先存入db沒關係,即使你是用BatchUpdateMode,這也可以作到的。當然如果有MasterDetail或甚至多層MasterDetail會有點麻煩,不過都不是大問題。都可以作到的。沒必要先存入db。
我看過你起的另一個用TField.OnValidEven的問題,我覺得你可能已把自己陷入一個本來怖必要的漩渦了。有很多人很喜歡用OnValidEven,不過在你的環境中,這是不適宜的。李維講的不一定對的。
你把涉及資料完整性須用交易保護的多檔異動分別存檔,且用到一個很可怕的DBGrid輸入界面,你的架構絕對會讓你費大功夫吃大苦頭的。
問題會很多的。

------
Kevin
monkeyhung
一般會員


發表:51
回覆:55
積分:21
註冊:2006-12-16

發送簡訊給我
#11 引用回覆 回覆 發表時間:2007-05-10 13:42:49 IP:203.69.xxx.xxx 訂閱


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

發送簡訊給我
#12 引用回覆 回覆 發表時間:2007-05-10 23:13:42 IP:61.219.xxx.xxx 訂閱
我瞭解你的意思了。
你這個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

發送簡訊給我
#13 引用回覆 回覆 發表時間:2007-05-10 23:58:10 IP:59.114.xxx.xxx 訂閱
大大真的勵害呀,一眼就看出的做法
若是我再多下這一段的話,可以這樣嗎
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

發送簡訊給我
#14 引用回覆 回覆 發表時間:2007-05-11 06:58:54 IP:61.219.xxx.xxx 訂閱
因為我的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

發送簡訊給我
#15 引用回覆 回覆 發表時間:2007-05-11 07:25:48 IP:61.219.xxx.xxx 訂閱
==>用批次更新及交易的架構
==>搭配一個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

發送簡訊給我
#16 引用回覆 回覆 發表時間:2007-05-11 07:35:32 IP:61.219.xxx.xxx 訂閱
為何我在---『訂單明細』Detail檔做新增的動作時,每要新增一筆都是會在第一列的地方輸入
而不是說在DBGrid的最後列耶,這樣會影響到我寫while not Query_PUR200D.DBGrid 時的動作嗎?
==>不會影響,只是會與User的直覺抵觸,會惹火User而矣。一般的感覺,新增應該出現在DBGrid的最下一列
==>通常會將DBGrid的新增鎖死,要User要新增一項定單明細一定在某一ColExit時才會啟動DetailQuery.Append,及在此時改與必要欄位的值,如定單編號及明細項編號等。
==>如果是批次更新,因此明細號尚未存入資料庫,要注意處理
==>DBGrid是很麻煩的異動界面
==>要上班了
------
Kevin
monkeyhung
一般會員


發表:51
回覆:55
積分:21
註冊:2006-12-16

發送簡訊給我
#17 引用回覆 回覆 發表時間:2007-05-14 15:05:02 IP:203.69.xxx.xxx 訂閱
大大我現在把它改成以下這樣的寫法了,但是為什麼我在輸入完單價後就會一直出現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

發送簡訊給我
#18 引用回覆 回覆 發表時間:2007-05-14 15:33:54 IP:219.87.xxx.xxx 訂閱

===================引 用 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

發送簡訊給我
#19 引用回覆 回覆 發表時間:2007-05-14 15:42:54 IP:203.69.xxx.xxx 訂閱
大大不是這樣子耶,我那幾行主要是讓那些欄位不能為空,但我現在只要在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

發送簡訊給我
#20 引用回覆 回覆 發表時間:2007-05-14 15:45:42 IP:219.87.xxx.xxx 訂閱

===================引 用 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

發送簡訊給我
#21 引用回覆 回覆 發表時間:2007-05-15 14:54:26 IP:61.219.xxx.xxx 訂閱
在我加入下列紅色的部份才會這樣的耶,怎會這樣呢???一直想不通
==>我不太敢明確的說,試推導如下:
==>假設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

發送簡訊給我
#22 引用回覆 回覆 發表時間:2007-05-15 15:05:27 IP:61.219.xxx.xxx 訂閱
其實你的問題不是很難解,不過你倒是真的選了一個很難作好的環境。
如果你要選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

發送簡訊給我
#23 引用回覆 回覆 發表時間:2007-05-15 15:25:49 IP:61.219.xxx.xxx 訂閱
你要把處理流程切割:
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

發送簡訊給我
#24 引用回覆 回覆 發表時間:2007-05-18 17:39:14 IP:203.69.xxx.xxx 訂閱
大大謝謝你的指導,讓我深深地了解自已真正問題的所在,而也逶過你的

解說,慢慢的把一些問題都迎刃而解,真的很謝謝你^^

日後若有叨擾到大大的地方,敬請見諒!!!
sam8832
一般會員


發表:1
回覆:1
積分:0
註冊:2008-04-25

發送簡訊給我
#25 引用回覆 回覆 發表時間:2008-04-26 00:26:04 IP:118.170.xxx.xxx 訂閱
我要設計按扭功能
dbgrid 的欄位有:日期 收入/支出 金額
我要有以下功能的程式碼
1.如何判斷是收入或支出
2.如何做加總動作
註:我有13筆資料
請大家幫忙

kevin2004
資深會員


發表:18
回覆:463
積分:416
註冊:2005-05-29

發送簡訊給我
#26 引用回覆 回覆 發表時間:2008-05-20 18:27:21 IP:118.161.xxx.xxx 訂閱
===================引 用 sam8832 文 章===================
我要設計按扭功能
dbgrid 的欄位有:日期 收入/支出 金額
我要有以下功能的程式碼
1.如何判斷是收入或支出
2.如何做加總動作
註:我有13筆資料
請大家幫忙
===================引 用 sam8832 文 章===================
這篇的東西已經太多了,而且DBGrid是一個很重要的輸入界面,你在本版再另起一個新題目,小弟再與你討論。
------
Kevin
系統時間:2024-04-25 14:56:29
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!