怎樣拿data? |
尚未結案
|
chyap99
一般會員 發表:20 回覆:51 積分:24 註冊:2004-03-31 發送簡訊給我 |
之前的問題連接
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=50681 invoice transaction pay 一個card_ID會在一頁
我要的output (by card id yap) 我要的output page2 (card id lum) 注:
-用戶能自己選擇要顯示的日期,如上為(1/6/2004-31/10/2004)
-用戶能自己選擇排列(如上日期為先).
-用戶能自己選擇Card_Id(如上yap, lum etc) 不好意思各位大大,小弟真的不知到要如何對這report下手,目前有几個難題想請教:
-我用(上面連結)的方法算balance,當page 2時, 它會把page1的balance接續著加起來,變成(10915.00), (11663.00), 而不是該有的(8000.00), (8748.00). -怎樣把不同的field變成一個report output 須要的field? 如在我的report output 的Date(日期), 是要拿tbl invoice(instalment是false的不用) 的Doc Date, 和tbl transaction(doc_type是INV的不用) 的Doc Date, 還有instalment 里的due date (截止日期), 而instalment的這個due date, 并沒有儲存在任何的table, 如用戶是在10/6/2004買貨,Tenor(供月期限)為60,那麼第一期的instalment due date為10/7/2004,第二期為10/8/2004,一直到60個月,而在report里如用戶要顯示report的日期為(1/6/2004-31/10/2004),那么就必須顯示這期間里所有instalment due date,要自己算然后放進report.
其時這report里還有很多條件和計算,但目前這個須要把几個table和不儲存在table的date變成report里的date,是小弟目前最不知該如和動手的問題.
實在須要各位大大的指點.如有不明白小弟問題的大大.請告知,小弟愿加以解說.
|
yachanga
資深會員 發表:24 回覆:335 積分:296 註冊:2003-09-27 發送簡訊給我 |
Hi chyap99您好:
您的問題真是又長又繁雜...難度真不低ㄟ..
因為小弟跟您討論過之前的問題, 依據之前的討論方向給您一點建議:
引言: -我用(上面連結)的方法算balance,當page 2時, 它會把page1的balance接續著加起來,變成(10915.00), (11663.00), 而不是該有的(8000.00), (8748.00).根據之前的討論, 您後來採用Chance36版大建議的ClientDataSet方法, 所以您可以在ClientDataSet中, 依據時間和Card ID 排序, 再根據Card ID 不同而重新計算balance. 看看這樣有沒有符合需求. 引言: -怎樣把不同的field變成一個report output 須要的field? 如在我的report output 的Date(日期), 是要拿tbl invoice(instalment是false的不用) 的Doc Date, 和tbl transaction(doc_type是INV的不用) 的Doc Date, 還有instalment 里的due date (截止日期), 而instalment的這個due date, 并沒有儲存在任何的table, 如用戶是在10/6/2004買貨,Tenor(供月期限)為60,那麼第一期的instalment due date為10/7/2004,第二期為10/8/2004,一直到60個月,而在report里如用戶要顯示report的日期為(1/6/2004-31/10/2004),那么就必須顯示這期間里所有instalment due date,要自己算然后放進report.ㄟ 說實在的可能是太複雜了 有聽沒有粉懂... 討論一下囉..如果您的Report date 是需要參考上述三個table後, 再去做運算. 試試看是否可以在ClientDataSet 加上一個report date , 然後把上面的運算結果填入此欄位. 我想可以先找出此三個table 關係, 用Key value來做join..然後再加以運算. 總之, 架構上以ClinetDataSet為主, 把所有複雜的邏輯在後端先運算好,塞入ClinetDataSet, 然後前端只要負責連結DataSet 和 DataField.. 用這個角度去思考, 會比較理想吧 < >< > ~悠遊法國號~ |
T.J.B
版主 發表:29 回覆:532 積分:497 註冊:2002-08-14 發送簡訊給我 |
嗯嗯嗯~~~~~~~~~
看完chyap99的問題
讓我有一種老鼠拉龜的感覺(粉無力)< >< >
哈哈 開開玩笑< >< > 1;你的Balance 總計 是放在某個Band上面嗎 如果是這樣 那你有兩個地方要做歸0的動作 不然會一直累加
一個是TQuickRep的OnBeforePrint事件
例如
BalanceSum := 0; 一個是放Balance 總計 的那個Band 的 onAfterPrint事件
例如
if BandPrinted then
begin
BalanceSum:=0;
end; 不過要注意喔
這樣做的前提是 你有用QrGroupBand 然後他的footerBand屬性是
設定為放Balance 總計 的那個Band 才會正確喔 如果你是別種做法 就令當別論
因為我不知道你報表Band的組合有哪些 至於第二個問題建議你用TempTable(暫存檔)的做法做
也就是create一個Report專用的Table 把資料存進去
因為用sql join 時間上不見的比較快
不過 要Try過才知道
而如果你用這種做法時 上面的balance總計問題就好解決了
就不是現在這個做法了 試試看吧
加油< >< > 天行健
君子當自強不息~~@.@
------
天行健 君子當自強不息~~@.@ |
chyap99
一般會員 發表:20 回覆:51 積分:24 註冊:2004-03-31 發送簡訊給我 |
謝謝大大們的回覆:
引言: 一個是TQuickRep的OnBeforePrint事件 例如 BalanceSum := 0; 一個是放Balance 總計 的那個Band 的 onAfterPrint事件 例如 if BandPrinted then begin BalanceSum:=0; end;T.J.B版主大大你好! 因為小弟是用report builder, 之前也有嘗試過用OnBeforePrint,但不能達到需求(之前連結),所以決定用ClientDataSet來計算balance.當然也不排除其它更快,更有效率的方法,一切以整個report需求為主. 引言: 至於第二個問題建議你用TempTable(暫存檔)的做法做 也就是create一個Report專用的Table 把資料存進去這也是其中一個小弟想到的方法(Temp Table),因為小弟還是新手, 其實也很想試試看ClientDataSet的用法,所以目前腦里想到的就是用ClientDataSet或Temp Table了,以整個report而言,大大認為那個較適合我呢?ClientDataSet 和 Temp Table小弟都沒做過. 引言:所以您可以在ClientDataSet中, 依據時間和Card ID 排序, 再根據Card ID 不同而重新計算balance.yachanga大大你好! 小弟用>< face="Verdana, Arial, Helvetica">引言:試試看是否可以在ClientDataSet 加上一個report date , 然後把上面的運算結果填入此欄位. 我想可以先找出此三個table 關係, 用Key value來做join..然後再加以運算. 用Key value來做join是指left outer join之類的嗎, 曾經試過這sql但會很慢(大量data時),我用FieldDefs.Add(‘Report Date’, ftDateTime, 0, FALSE);當我create這個report date之後,想知到要如何把兩個table(tbl invoice和 tbl transaction)的Doc_Date填入呢, 之後還要加上我計算出來的due_date, 所以須要report date = tbl invoice doc_date tbl transaction doc_date due date. 其實小弟也了解自己的表達能力不太好,但又怕寫太多會讓大大們連看都懶得要看,這里小弟再做些補充.
|
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
chyap99 你好
還記得這一段嗎?若要在分頁的部份重新計算Balance // 建立Procedure 供呼叫用 Procedure TForm1.ReCala; Var Bal ,Amount : Real; bm : TBookMark; cKey : String;; // 判斷分頁用的變數 Begin With CDS DO Begin mb := GetBookMark; // 記錄目前指標 First; cKey := '' ; While Not Eof Do Begin If cKey <> (FieldByName('Document_Date').AsString ' ' FieldByName('Card_ID').AsString ) Then // Document_Date+Card_ID不同時要歸零 cKey := (FieldByName('Document_Date').AsString ' ' FieldByName('Card_ID').AsString ); Bal := 0 ; End; Edit; Bal := Bal FieldByName('Debit').AsFloat-FieldByName('Credit').AsFloat; FieldByName('Balance').AsFloat := Bal; Post; Next; End; GotoBookMark(bm); // 還原指標 End; End; |
chyap99
一般會員 發表:20 回覆:51 積分:24 註冊:2004-03-31 發送簡訊給我 |
|
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
chyap99 你好
提供操作的步驟,如下 1.建立輸出用的資料集(使用TClientDataSet) With cds Do Begin Close; FieldDefs.Add('Card_ID',ftString,20,False); ...... FieldDefs.Add('Type' ,ftString,10,False); FieldDefs.Add('Amount' ,ftFloat ,0,False); FieldDefs.Add('Debit' ,ftFloat ,0,False); FieldDefs.Add('Credit' ,ftFloat ,0,False); FieldDefs.Add('Balance',ftFloat ,0,False); CreateDataSet; End; // 之後就是開啟的狀態,不要再Open了。 2.開始收集各Table的資料 // 取得Invoice的資料 Query1.SQL.text := 'Select * From INVOICE Where ......' ; Query1.Open; While Not Query1.Eof Do Begin CDS.Append; CDS.FieldByName('Card_ID').AsString := Query1.FieldByName('Card_ID').AsString; CDS.FieldByName(Type').AsString := 'INV'; .......... CDS.FieldByName('Amount').AsFloat := Query1.FieldByName('Amount').AsFloat; CDS.Post; Query1.Next; End; // 取得Transation的資料 Query1.SQL.text := 'Select * From Transation Where ......' ; Query1.Open; While Not Query1.Eof Do Begin CDS.Append; CDS.FieldByName('Card_ID').AsString := Query1.FieldByName('Card_ID').AsString; CDS.FieldByName(Type').AsString := 'TRN'; .......... CDS.FieldByName('Amount').AsFloat := Query1.FieldByName('Amount').AsFloat; CDS.Post; Query1.Next; End; .... .... .... ReCala ; // 計算Balance |
chyap99
一般會員 發表:20 回覆:51 積分:24 註冊:2004-03-31 發送簡訊給我 |
謝謝Chance36版主的回复:
其實這兩天小弟已一直在嘗試了(自己也該加油),Client Data Set(cds)應該已經'成功'收集到其他Table的資料了,其實方法和版主的很像,只是小弟用兩個query和預先把sql寫好而已,但在計算就遇到麻煩了,不知是否能解釋的清楚. 小弟的方法,如有缺點請告知:
iMonthCount, iMonth :Integer;
sqlHpStt.Close; //query for select data from tbl transaction.
sqlHpStt.Open;
sqlCIM.Close; //query for tbl invoice
sqlCIM.Open;
With cds Do Begin
close;
FieldDefs.Add('Date',ftDateTime, 0, FALSE );
...........
CreateDataSet;
While Not sqlHpStt.Eof Do Begin
Append;
FieldByname('Date').AsDateTime := sqlHpSttDocument_Date.Value ;
............
Post;
sqlHpStt.Next;
End;
While Not sqlCIM.Eof Do Begin
Append;
FieldByname('Date').AsDateTime := sqlCIMDocument_Date.Value ;
..............
End;
post;
sqlCIM.Next;
end;
sqlCIM.Close;
sqlCIM.Open;
While Not sqlCIM.Eof Do Begin
sqlGeneral.SQL.Clear; //empty query
sqlGeneral.SQL.Add(' SELECT SUM(Amount),Match_Invoice FROM AcHPStt WHERE Card_Id = :pCustId AND Match_Invoice = :pMatchDoc GROUP BY Card_Id,Match_Invoice '); //AcHPStt=transaction tbl
sqlGeneral.ParamByName('pCustId').AsString := FieldByname('Card_ID').AsString;
sqlGeneral.ParamByName('pMatchDoc').AsString := FieldByname('Doc_No').AsString;
sqlGeneral.Prepare; sqlGeneral.Open; sqlGeneral.Last;
currLoan := sqlCIMLoan.AsCurrency ;
iMonth := sqlCIMTenor.Value;
for iMonthCount := 1 to iMonth do begin
currOutStanding := RoundCurrency(CalOutStanding(currLoan,currPrincipal),2);
Append;
FieldByname('Date').AsDateTime := IncMonth(sqlCIM.FieldByName('Document_Date').AsDateTime,iMonthCount);
...............
End;
Post;
sqlCIM.Next ;
End;
First;
End;
sqlHpStt.Close;
sqlCIM.Close;
cds.IndexFieldNames := 'Card_ID;Date'; ReCala ; (問題在下面的回應)
|
chyap99
一般會員 發表:20 回覆:51 積分:24 註冊:2004-03-31 發送簡訊給我 |
小弟用這(以上)方法算出了一些資料然後把它也填入cds里,填入資料如上圖,現有一些問題想請教:
|
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
chyap99 你好 你這好像類似分期付款或短期小額信用貸款的還款試算表吧!這個問題不用回答。 看得出來你很努力的在描述問題,我也很努力的在瞭解你的問題,但是,不好意思,還是沒有很清楚的瞭解你的問題,不過就我所瞭解的部份,試著提供一些建議,看是否可以符合你的需求。
引言: 1.先確定時間點,如10~12月,則01/10/2004及31/12/2004是 兩個時間關鍵點,< 01/10/2004 者為之前(或稱期初)兩時間點之間者為目前(或稱本期),兩者彙總的 結果為之後(或稱期末) 2.使用之前同樣的技巧,建立TClientDataSet,包含主鍵欄位,分頁欄位及期別欄位及借貨和餘額欄位 3.開始收集各Table的資料 Var DD, D1, D2 : TDate; SectName : String ; Begin D1 := StrToDate('01/10/2004') D2 := StrToDate('31/12/2004') // SectID即為期別欄位名 cds.IndexFieldName := 'Card_ID....;SectID' ; // 先建立動態索引(鍵值及期別,欄位間用';'分開) // 取得Invoice的資料 Query1.SQL.text := 'Select * From INVOICE Where ......' ; Query1.Open; While Not Query1.Eof Do Begin // 判斷日期區間 DD := Query1.FieldByName('xxxDate').AsDate ; If DD < D1 Then Begin SectName := '期初' ; //或直接寫'01/10/2004前' 亦可 End Else If DD <= D2 Then Begin SectName := '本期' ; //或直接寫'01/10/2004~31/12/2004' 亦可 End Else Begin // 之後的記錄不用算吧 Query1.Next; Continue; End; CDS.SetKey; // 準備搜尋資料(搜尋的欄位必須有建立索引) CDS.FieldByName('Card_ID').AsString := Query1.FieldByName('Card_ID').AsString ; ......其他鍵值欄位也就是建索引的那幾個欄位 CDS.FieldByName('SectNo').AsString := SectName; If Not CDS.GotoKey Then Begin // 找相同的鍵值 CDS.Append; //找不到則新增一筆 CDS.FieldByName('Card_ID').AsString := Query1.FieldByName('Card_ID').AsString ; ......其他鍵值欄位 CDS.FieldByName('SectNo').AsString := SectName; End Else Begin CDS.Edit; // 找到則直接進入修改狀態 End; //在此依據帳款別判斷後寫入個別的借貨欄位(注意要用累加的方式) CDS.FieldByName('Amount').AsFloat := CDS.FieldByName('Amount').AsFloat Query1.FieldByName('Amount').AsFloat; CDS.Post; Query1.Next; End; // 取得Transation的資料 ......PS:嘿嘿!紅配綠.........只為了要分隔一下區段而已,不然全紅或全綠還是分辨不出重點的。 發表人 - chance36 於 2004/06/18 02:22:55 |
chyap99
一般會員 發表:20 回覆:51 積分:24 註冊:2004-03-31 發送簡訊給我 |
謝謝Chance36版主的回复: 小弟想做的正是分期付款的還款試算表.如有十期付款(一月到十月)用戶選擇顯示六到八月的還款試算,小弟就要把本期(六到八月的還款試算)顯示在報表,以及找出期初(一到五月)用戶的還款記錄,看看是否還有欠債,只須把期初的總數(可能是欠債或是預先付的還款)帶出即可,然后還要找出期末(九到十月)還必須給的還款,再把所有(期初,本期,期末)的還款計算在一起,成為另一個'總共'還須要給的還款的欄位(Oustanding) . 小弟已經收集到所須要Table的資料,也能把它加在cds里,想知到是應該先跟據用戶所選擇的日期,Card_ID來把所須要的資料從Table過濾了再加進cds里, 還是該先把所有資料加進了cds里(小弟目前是這樣),才來根據用戶所選擇的日期,Card_ID把資料從cds里過濾出來?小弟所做的格式是能讓用戶先從TDBLookupCombo選擇日期,再按Button來觀看/Print Report.還有,請問大大是不是該用cds.filtered 來從cds里過濾所須要的資料? 大大的coding小弟有些不明白,不知大大能否再做些解釋?
引言: CDS.SetKey; // 準備搜尋資料(搜尋的欄位必須有建立索引) CDS.FieldByName('Card_ID').AsString := Query1.FieldByName('Card_ID').AsString ; ......其他鍵值欄位也就是建索引的那幾個欄位 CDS.FieldByName('SectNo').AsString := SectName; If Not CDS.GotoKey Then Begin // 找相同的鍵值 CDS.Append; //找不到則新增一筆 CDS.FieldByName('Card_ID').AsString := Query1.FieldByName('Card_ID').AsString ; ......其他鍵值欄位 CDS.FieldByName('SectNo').AsString := SectName; End Else Begin CDS.Edit; // 找到則直接進入修改狀態 End;其實CDS.SetKey;是要建立期初,本期,期末的索引(根據上例子)對嗎?所以一定要有CDS.FieldByName('SectNo').AsString := SectName;這段?而這('SectNo')是不是cds.IndexFieldName := 'Card_ID....;SectID' ;的SectID來的? 當If Not CDS.GotoKey Then Begin,程式會去找出什麼相同的鍵值?期初?本期?小弟在嘗試這coding時,每個record都會append進cds.而End Else Begin CDS.Edit;又要修改什麼呢? 不好意思還要麻煩大大解說一下. 感激! |
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
chyap99 你好
{ CDS.SetKey; // 準備搜尋資料(搜尋的欄位必須有建立索引) CDS.FieldByName('Card_ID').AsString := Query1.FieldByName('Card_ID').AsString ; ......其他鍵值欄位也就是建索引的那幾個欄位 CDS.FieldByName('SectNo').AsString := SectName; If Not CDS.GotoKey Then Begin // 找相同的鍵值 } // 以上也可以寫成如下locate的動作 If Not CDS.Locate('Card_ID....;SectID' ,VarArrayOf([Query1.FieldByName('Card_ID').AsString, ..., SectName]),[]) Then Begin CDS.Append; //找不到則新增一筆 CDS.FieldByName('Card_ID').AsString := Query1.FieldByName('Card_ID').AsString ; ......其他鍵值欄位 CDS.FieldByName('SectNo').AsString := SectName; End Else Begin CDS.Edit; // 找到則直接進入修改狀態 End;用SetKey必須搭配索引,而用locate則有沒有索引都可以運作只是沒有索引時速度會較慢(資料量愈多慢的愈多...到受不了)若有搭配索引則差不了多少(與setKey比較),其他的稍候....再補充吧! |
chyap99
一般會員 發表:20 回覆:51 積分:24 註冊:2004-03-31 發送簡訊給我 |
謝謝Chance36版主的回复:
引言: 用SetKey必須搭配索引,而用locate則有沒有索引都可以運作只是沒有索引時速度會較慢(資料量愈多慢的愈多...到受不了)若有搭配索引則差不了多少(與setKey比較),其他的稍候....再補充吧!不好意思一直麻煩大大,但小弟還是不明白該怎么用(先別理locate了,想先了解SetKey)....不知為何試來試去總是不明白. 引言: 想知到是應該先跟據用戶所選擇的日期,Card_ID來把所須要的資料從Table過濾了再加進cds里, 還是該先把所有資料加進了cds里(小弟目前是這樣),才來根據用戶所選擇的日期,Card_ID把資料從cds里過濾出來? 當If Not CDS.GotoKey Then Begin,程式會去找出什麼相同的鍵值?期初?本期?小弟在嘗試這coding時,每個record都會append進cds.而End Else Begin CDS.Edit;又要修改什麼呢?是不是索引設置的不對呢? |
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
引言: if SectName= 'before' then begin //找期初...[/green] before := before sqlHpStt.FieldByName('Amount').AsCurrency; CDS.FieldByName('Amount').AsCurrency := before; end;chyap99 你好 改成這樣 // if SectName= 'before' then begin //找期初...[/green] //before := before sqlHpStt.FieldByName('Amount').AsCurrency; CDS.FieldByName('Amount').AsCurrency := CDS.FieldByName('Amount').AsCurrency sqlHpStt.FieldByName('Amount').AsCurrency ; //end; 最後CDS的結果 會如下所示 [Card_ID] [Date] [SectNo] [Doc_No] [Match_Invoice] [Type] [Amount] YAP xx/.. befor ..... ..... .... 9999 YAP xx/.. after ..... ..... .... 9999 以目前資料狀況來看似乎[Date]欄位不能,因為此程式的目的即是將日期依時間點的不同,轉化為Befor及After兩個時間區間,所以程式改為如下(把Date從鍵值欄位中去除) var DD, D1, D2 : TDate; SectName : String ; Begin D1 := StrToDate('01/06/2004');//dtpStaDate.Date; D2 := StrToDate('01/01/2005');//dtpEndDate.Date; sqlHpStt.Close; sqlHpStt.Open; With cds Do Begin close; FieldDefs.Add( 'Card_ID',ftString, 10, FALSE ); FieldDefs.Add( 'SectName',ftString, 30, FALSE ); -------------- CreateDataSet; cds.IndexFieldNames := 'Card_ID;Doc_No;Match_Invoice;Type;SectNo'; While Not sqlHpStt.Eof Do Begin DD := sqlHpStt.FieldByName('Document_Date').AsDateTime; If DD < D1 Then Begin SectName := 'before ' DateToStr(D1) ; End Else If DD <= D2 Then Begin SectName := 'Between ' DateToStr(D1) ' ' DateToStr(D2) ; End Else Begin sqlHpStt.Next; Continue; End; CDS.SetKey; CDS.FieldByName('Card_ID').AsString := sqlHpStt.FieldByName('Card_ID').AsString ; CDS.FieldByname('Doc_No').AsString := sqlHpStt.FieldByName('Document_No').AsString ; CDS.FieldByname('Match_Invoice').AsString := sqlHpStt.FieldByName('Match_Invoice').AsString ; CDS.FieldByname('Type').AsString := sqlHpStt.FieldByName('Document_Type').AsString ; CDS.FieldByName('SectName').AsString := SectName; If Not CDS.GotoKey Then Begin CDS.Append; // 找不到鍵值則新增一筆記錄 CDS.FieldByName('Card_ID').AsString := sqlHpStt.FieldByName('Card_ID').AsString ; CDS.FieldByName('Date').AsDateTime := sqlHpStt.FieldByName('Document_Date').AsDateTime; CDS.FieldByName('SectNo').AsString := SectName; CDS.FieldByname('Doc_No').AsString := sqlHpStt.FieldByName('Document_No').AsString ; CDS.FieldByname('Match_Invoice').AsString := sqlHpStt.FieldByName('Match_Invoice').AsString ; CDS.FieldByname('Type').AsString := sqlHpStt.FieldByName('Document_Type').AsString ; End Else Begin CDS.Edit; End; // 累加 CDS.FieldByName('Amount').AsCurrency := CDS.FieldByName('Amount').AsCurrency sqlHpStt.FieldByName('Amount').AsCurrency; CDS.Post; sqlHpStt.Next; //end; End; 最後CDS的結果 會如下所示 [Card_ID] [SectName] [Doc_No] [Match_Invoice] [Type] [Amount] YAP Before 01/06/2004 ..... ..... .... 9999 YAP between 01/06/2004 01/01/2005 ..... ..... .... 9999發表人 - chance36 於 2004/06/24 14:21:47 |
chyap99
一般會員 發表:20 回覆:51 積分:24 註冊:2004-03-31 發送簡訊給我 |
謝謝Chance36版主的回复:
引言: // 累加 CDS.FieldByName('Amount').AsCurrency := CDS.FieldByName('Amount').AsCurrency sqlHpStt.FieldByName('Amount').AsCurrency; CDS.Post; sqlHpStt.Next; //end; End;小弟依照大大的方式,CDS.FieldByName('Amount').AsCurrency 并不會累加,小弟是在開始收集各Table的資料時寫入以上程式. ------------------------------------------------------------------- (header band) [card_id] = Yap (page group by card id) [outstanding] = 9999 // 本期的最后balance 期末的balance ------------------------------------------------------------------ (Detail Band) [Date] [Doc_No] [Match_Inv] [Type] [Debit] [Credit] [Balance] before B/F 2000 //期初的總數帶出. 12/6/2004 … … … (500) 1500 1/7/2004 … … … (500) 1000 … … … … … 31/12/2004 … … … 200 1200 //本期的最后balance ----------------------------------------------------------------以上是小弟想要的report output.
|
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
chyap99 你好
var DD, D1, D2 : TDate; // SectName : String ; IsFirst : Boolean ; // 是否為期初 Begin D1 := StrToDate('01/06/2004');//dtpStaDate.Date; D2 := StrToDate('01/01/2005');//dtpEndDate.Date; sqlHpStt.Close; sqlHpStt.Open; With cds Do Begin close; FieldDefs.Add( 'Card_ID',ftString, 10, FALSE ); -------------- CreateDataSet; cds.IndexFieldNames := 'Card_ID;Date;Doc_No;Match_Invoice;Type'; While Not sqlHpStt.Eof Do Begin DD := sqlHpStt.FieldByName('Document_Date').AsDateTime; IsFirst := False; // 是否為期初 If DD < D1 Then Begin DD := D1 ; IsFirst := True; // 是否為期初 End Else If DD > D2 Then Begin sqlHpStt.Next; Continue; End; If IsFirst Then Begin // 若為期初資料須先到後再 累加 CDS.SetKey; CDS.FieldByName('Card_ID').AsString := sqlHpStt.FieldByName('Card_ID').AsString ; CDS.FieldByname('Date').AsDateTime := DD; // <====== CDS.FieldByname('Doc_No').AsString := sqlHpStt.FieldByName('Document_No').AsString ; CDS.FieldByname('Match_Invoice').AsString := sqlHpStt.FieldByName('Match_Invoice').AsString ; CDS.FieldByname('Type').AsString := sqlHpStt.FieldByName('Document_Type').AsString ; CDS.FieldByName('SectName').AsString := SectName; If Not CDS.GotoKey Then Begin CDS.Append; // 找不到鍵值則新增一筆記錄 End Else Begin CDS.Edit; End; End Else Begin CDS.Append; // 不是期初資料一律用新增的方式 End; If CDS.State IN [dsInsert] Then Begin CDS.FieldByName('Card_ID').AsString := sqlHpStt.FieldByName('Card_ID').AsString ; CDS.FieldByName('Date').AsDateTime := DD; If IsFirst Then Begin CDS.FieldByname('Doc_No').AsString := 'before B/F' ; CDS.FieldByname('Match_Invoice').AsString := ''; CDS.FieldByname('Type').AsString := ''; End Else Begin CDS.FieldByname('Doc_No').AsString := sqlHpStt.FieldByName('Document_No').AsString ; CDS.FieldByname('Match_Invoice').AsString := sqlHpStt.FieldByName('Match_Invoice').AsString ; CDS.FieldByname('Type').AsString := sqlHpStt.FieldByName('Document_Type').AsString ; End; End; // 累加 // 加項 If sqlHpStt.FieldByName('Document_Type').AsString='INV' Then Begin CDS.FieldByName('Debit').AsCurrency := CDS.FieldByName('Debit').AsCurrency sqlHpStt.FieldByName('Amount').AsCurrency; End; // 減項 If sqlHpStt.FieldByName('Document_Type').AsString='PAY' Then Begin CDS.FieldByName('Credit').AsCurrency := CDS.FieldByName('Credit').AsCurrency sqlHpStt.FieldByName('Amount').AsCurrency; End; CDS.Post; sqlHpStt.Next; //end; End; 最後重算Balance |
chyap99
一般會員 發表:20 回覆:51 積分:24 註冊:2004-03-31 發送簡訊給我 |
謝謝Chance36版主的回复:
[Date] [Doc_No] [Match_Inv] [Type] [Debit] [Credit] [Balance] 1/6/2004 before B/F //期初的總數帶出. 1/6/2004 before B/F … … … ... ... 12/6/2004 … … … (500) 1500 1/7/2004 … … … (500) 1000 … … … … … 31/12/2005 … … … 200 1200 //本期的最后balance小弟測試了之後,before B/F會不斷append(有几個期初的record就會append几個),而小弟只要顯示一個before B/F來把期初的總數帶出,就是所有期初的累加,而不需把期初的每筆record詳敘帶出. 引言: // 累加 // 加項 If sqlHpStt.FieldByName('Document_Type').AsString='INV' Then Begin CDS.FieldByName('Debit').AsCurrency := CDS.FieldByName('Debit').AsCurrency sqlHpStt.FieldByName('Amount').AsCurrency; End; // 減項 If sqlHpStt.FieldByName('Document_Type').AsString='PAY' Then Begin CDS.FieldByName('Credit').AsCurrency := CDS.FieldByName('Credit').AsCurrency sqlHpStt.FieldByName('Amount').AsCurrency; End;小弟只要把期初的sqlHpStt.FieldByName('Amount').AsCurrency;加起來,所以以上的程式可能用不到,但如換成 CDS.FieldByName('Amount').AsCurrency := CDS.FieldByName('Amount').AsCurrency sqlHpStt.FieldByName('Amount').AsCurrency; 它又不會把所有期初的sqlHpStt.FieldByName('Amount').AsCurrency; 累加起來. 期末和期初一樣,不須顯示在report,但也要計算出期末的balance,小弟也想知到該怎么計算. 再次謝謝版主的幫助!! |
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
|
chyap99
一般會員 發表:20 回覆:51 積分:24 註冊:2004-03-31 發送簡訊給我 |
謝謝Chance36版主的回复:
跟據版主的方法,小弟在取完第一個table的資料,繼續拿取下個所須的資料時,做了些修改,不知會否有問題:
假設小弟已經取得第一個table的資料,以下為繼續拿取下個所須資料時的coding.
While Not sqlHpStt.Eof Do Begin .......... if sqlHpSttAmount.Value > 0 then begin If IsFirst Then Begin CDS.FieldByName('Balance').AsCurrency := CDS.FieldByName('Balance').AsCurrency sqlHpSttAmount.Value End Else Begin CDS.FieldByname('Debit').AsCurrency := sqlHpSttAmount.Value ; end; ................................. CDS.Post; sqlHpStt.Next; End; //繼續拿取下個所須資料 While Not sqlCIM.Eof Do Begin sqlGeneral.SQL.Clear; sqlGeneral.SQL.Add(' SELECT SUM(Amount),Match_Invoice FROM AcHPStt WHERE Card_Id = :pCustId AND Match_Invoice = :pMatchDoc GROUP BY Card_Id,Match_Invoice '); sqlGeneral.ParamByName('pCustId').AsString := CDS.FieldByname('Card_ID').AsString; ............................ iMonth := sqlCIMTenor.Value; //供期 currIntlAmt := CalIntlAmount(currLoan,currTermCharge,iMonth); for iMonthCount := 1 to iMonth do begin currOutStanding := RoundCurrency(CalOutStanding(currLoan,currPrincipal),2); DD := IncMonth(sqlCIM.FieldByName('Document_Date').AsDateTime,iMonthCount); IsFirst := False; If DD < D1 Then Begin IsFirst := True; DD := D1 ; End Else If DD > D2 Then Begin //sqlCIM.Next; //如有此coding不能加到新欄位 Continue; End; If IsFirst Then Begin CDS.SetKey; CDS.FieldByName('Card_ID').AsString := sqlCIM.FieldByName('Card_ID').AsString ; CDS.FieldByname('Date').AsDateTime := DD; If Not CDS.GotoKey Then Begin CDS.Append; End Else Begin CDS.Edit; End; End Else Begin CDS.Append; End; If CDS.State IN [dsInsert] Then Begin CDS.FieldByName('Card_ID').AsString := sqlCIM.FieldByName('Card_ID').AsString ; CDS.FieldByName('Date').AsDateTime := DD; If IsFirst Then Begin ............. CDS.FieldByName ('Particulars').AsString := 'Balance B/F'; End Else Begin ....................... CDS.FieldByname('Particulars').AsString := 'Installment# ' inttostr(iMonthCount); CDS.FieldByname('Debit').AsCurrency := currIntlAmt; End; End; If IsFirst Then Begin CDS.FieldByName('Balance').AsCurrency := CDS.FieldByName('Balance').AsCurrency currIntlAmt; end; End; CDS.Post; sqlCIM.Next; End; ReCala ;暫時好像還沒什么問題(計算期初方面),至於期末,如在 End Else If DD > D2 Then Begin這行加個類似IsFirst的code行得通嗎,目前小弟還在測試中,另外小弟也還須要做些0-30天(本月的balance), 30-60(上個月balance)的欄位等.. |
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
chyap99 你好
While Not sqlHpStt.Eof Do Begin // Continue 後會執行此處 DD := sqlHpStt.FieldByName('Document_Date').AsDateTime; IsFirst := False; If DD < D1 Then Begin IsFirst := True; DD := D1 ; End Else If DD > D2 Then Begin IsLast := True; //期末時... sqlHpStt.Next; Continue; //回到迴圈的起始位繼續執行 end; If IsLast Then Begin //不會執行.. CDS.SetKey; CDS.FieldByName('Card_ID').AsString := sqlHpStt.FieldByName('Card_ID').AsString ; CDS.FieldByname('Date').AsDateTime := DD; after := after sqlHpSttAmount.Value; end; ....... 如上說明,Continue ; 會跳過迴圈內的其他程式碼,直接回到迴圈的開始位置繼續執行,所以後面的 If Islast ..就執行不到了, 以你的需求應該把Continue;拿掉才是(現在才了解你所謂的期末是指截止日之後的所有總合) |
chyap99
一般會員 發表:20 回覆:51 積分:24 註冊:2004-03-31 發送簡訊給我 |
謝謝Chance36版主的回复:
While Not sqlHpStt.Eof Do Begin // Continue 後會執行此處 DD := sqlHpStt.FieldByName('Document_Date').AsDateTime; IsFirst := False; If DD < D1 Then Begin IsFirst := True; DD := D1 ; End Else If DD > D2 Then Begin IsLast := True; //期末時... sqlHpStt.Next; //Continue; //回到迴圈的起始位繼續執行 (拿掉) end;如把Continue;拿掉,截止日之後的所有record都會Append進報表,但小弟只要拿截止日之後的累加總合. |
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
引言: 如把Continue;拿掉,截止日之後的所有record都會Append進報表,但小弟只要拿截止日之後的累加總合.chyap99 你好 要累計加總,就要想辦法讓它有相同的鍵值,以下修改部份就是讓大於D2日期 的記錄,搜尋時使用相用相同的DD日期(=d2 1),而不使用原記錄的日期 While Not sqlHpStt.Eof Do Begin // Continue 後會執行此處 DD := sqlHpStt.FieldByName('Document_Date').AsDateTime; IsFirst := False; If DD < D1 Then Begin IsFirst := True; DD := D1 ; End Else If DD > D2 Then Begin IsLast := True; //期末時... sqlHpStt.Next; DD := D2 1 ; // 加這行 //Continue; //回到迴圈的起始位繼續執行 (拿掉) end; |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |