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

怎樣拿data?

尚未結案
chyap99
一般會員


發表:20
回覆:51
積分:24
註冊:2004-03-31

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-06-14 09:58:55 IP:219.95.xxx.xxx 未訂閱
之前的問題連接 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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-06-14 12:47:40 IP:210.68.xxx.xxx 未訂閱
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

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-06-14 14:22:53 IP:61.220.xxx.xxx 未訂閱
嗯嗯嗯~~~~~~~~~ 看完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

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-06-14 21:06:07 IP:219.95.xxx.xxx 未訂閱
謝謝大大們的回覆:     
引言: 一個是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. 其實小弟也了解自己的表達能力不太好,但又怕寫太多會讓大大們連看都懶得要看,這里小弟再做些補充.
  • 小弟想知到如何(一些主要coding)把几個table的field,和自己計算的資料填入一個field(如report date)
  • 計算的資料如due date和其它資料應該在什麼事件地方中計算然后再把它填入我create的欄位?每次run時計算能怎樣避免速度太慢?
  • 其實還沒真正想過計算的部份(先解決以上兩點),如何計算才是最好,每一次Run時該如和避免重复和能拿到須要的,如計算1-60的instalment可能用戶只要拿4-15的instalment來看
-還不能向老板確定...只好繼續努力了!- 發表人 - chyap99 於 2004/06/14 21:28:03
Chance36
版主


發表:31
回覆:1033
積分:792
註冊:2002-12-31

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-06-14 22:09:16 IP:211.20.xxx.xxx 未訂閱
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

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-06-15 09:56:58 IP:219.95.xxx.xxx 未訂閱
謝謝Chance36版主, 加入版主的coding(刪除了日期部份),balance的問題就解決了. 現在就剩下其它的問題了.好像如何用CDS把几個table的field,和自己計算的資料填入我自己create的欄位等... 當然也很希望能得到(版主和各位大大)幫助.
Chance36
版主


發表:31
回覆:1033
積分:792
註冊:2002-12-31

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-06-16 21:20:41 IP:211.20.xxx.xxx 未訂閱
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

發送簡訊給我
#8 引用回覆 回覆 發表時間:2004-06-17 21:49:59 IP:219.95.xxx.xxx 未訂閱
謝謝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

發送簡訊給我
#9 引用回覆 回覆 發表時間:2004-06-17 21:57:50 IP:219.95.xxx.xxx 未訂閱
小弟用這(以上)方法算出了一些資料然後把它也填入cds里,填入資料如上圖,現有一些問題想請教:
  • 在cds里該用什么方法把填入的資料拿出放進Report里?如用戶要選擇10月到12月的data, card_id是yap的?小弟想到的是用filter把要的data拿出, 是這樣嗎?
  • 小弟須要算Outstanding(還欠的錢),這讓小弟想了好久…舉例如用戶選擇10月到12月的data for ‘tan’(如圖),report就會把instalment4,5,6的data拿出(amount放在debit =未還), (注:已經給過的payment會儲存在tbl transaction, amount為負數放在credit=已還.) 這時就要找出之前(10月前所有還沒給清的錢-須填為新一欄位),加10月到12月里沒給清的錢,以及加12月后沒給(須要給)的錢成為outstanding.(圖里的outstanding為當用戶還到那期(instalment)時因該會欠的錢,不是小弟要的Outstanding)
  • 還要算current(這個月)欠的錢-如以上例子(用戶選擇10月到12月)current為12月欠的錢.
  • 30-60days- 為30-60天前(11月)欠的錢.
  • 60-90days- 為60-90天前(10月)欠的錢.
  • 90-120days-為90-120天前(9月)欠的錢.
  • >120days-為>120天前(8月前)欠的錢.
備注: [list]
  • 一個card_id是可以有几個instalment的,outstanding是算給那card_id的.
  • Cds 的欄位可以增加如可方便計算.
  • 其實大大可不理計算的成式,debit-credit(balance)就是還欠的錢了,小弟只想知到怎樣根據用戶日期的選擇找出之前,現在和之後的欠債.
  • 小弟也很明白自己說的很亂,還是一樣如有疑問小弟可再解說清楚.
    Chance36
    版主


    發表:31
    回覆:1033
    積分:792
    註冊:2002-12-31

    發送簡訊給我
    #10 引用回覆 回覆 發表時間:2004-06-18 02:10:45 IP:203.204.xxx.xxx 未訂閱
    chyap99 你好     你這好像類似分期付款或短期小額信用貸款的還款試算表吧!這個問題不用回答。    看得出來你很努力的在描述問題,我也很努力的在瞭解你的問題,但是,不好意思,還是沒有很清楚的瞭解你的問題,不過就我所瞭解的部份,試著提供一些建議,看是否可以符合你的需求。
    引言:
      .一個card_id是可以有几個instalment的,outstanding是算給那card_id的. .Cds 的欄位可以增加如可方便計算. .其實大大可不理計算的成式,debit-credit(balance)就是還欠的錢了,小弟只想知到怎樣根據用戶日期的選擇找出之前,現在和之後的欠債.
    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

    發送簡訊給我
    #11 引用回覆 回覆 發表時間:2004-06-21 22:14:38 IP:219.95.xxx.xxx 未訂閱
    謝謝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

    發送簡訊給我
    #12 引用回覆 回覆 發表時間:2004-06-21 22:48:50 IP:211.20.xxx.xxx 未訂閱
    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

    發送簡訊給我
    #13 引用回覆 回覆 發表時間:2004-06-23 19:20:10 IP:219.95.xxx.xxx 未訂閱
    謝謝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

    發送簡訊給我
    #14 引用回覆 回覆 發表時間:2004-06-24 14:18:22 IP:211.20.xxx.xxx 未訂閱
    引言: 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

    發送簡訊給我
    #15 引用回覆 回覆 發表時間:2004-06-24 16:33:29 IP:219.95.xxx.xxx 未訂閱
    謝謝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.
    • 在Detail Band里, 第一個要顯示的'期初的總數帶出' 是所有期初的累加,而不需把期初的每筆record詳敘帶出.
    • 所有本期的每筆record都要在Detail Band里顯示.
    • 期末和期初一樣,不須顯示在report,只需找出期末的balance再和本期的最后balance相加,就能找出outstanding(還剩的欠債)
    • 用戶是在run time時選擇的日期,程式才能去執行(如分別本期..計算...等)
    • report是group by card_id,一個card_id(如yap)會開始全新的一頁,而detail band則是跟據日期來排列.
    • [*]
    根據大大的方法,小弟該如和做到我想要的這個report呢? 感謝大大!! 發表人 - chyap99 於 2004/06/24 16:36:11
    Chance36
    版主


    發表:31
    回覆:1033
    積分:792
    註冊:2002-12-31

    發送簡訊給我
    #16 引用回覆 回覆 發表時間:2004-06-24 17:02:43 IP:211.20.xxx.xxx 未訂閱
    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

    發送簡訊給我
    #17 引用回覆 回覆 發表時間:2004-06-24 19:21:37 IP:219.95.xxx.xxx 未訂閱
    謝謝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

    發送簡訊給我
    #18 引用回覆 回覆 發表時間:2004-06-24 20:29:45 IP:211.20.xxx.xxx 未訂閱
    引言: 小弟測試了之後,before B/F會不斷append(有几個期初的record就會append几個),而小弟只要顯示一個before B/F來把期初的總數帶出,就是所有期初的累加,而不需把期初的每筆record詳敘帶出.
    chyap99 你好
      以上是失誤了!!再試試以下程式     > >{  // 以下省了,只要AsString='INV'AsString='PAY'>
    發表人 - chance36 於 2004/06/24 20:34:36
    chyap99
    一般會員


    發表:20
    回覆:51
    積分:24
    註冊:2004-03-31

    發送簡訊給我
    #19 引用回覆 回覆 發表時間:2004-06-29 18:33:03 IP:219.95.xxx.xxx 未訂閱
    謝謝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

    發送簡訊給我
    #20 引用回覆 回覆 發表時間:2004-07-06 17:35:51 IP:211.20.xxx.xxx 未訂閱
    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

    發送簡訊給我
    #21 引用回覆 回覆 發表時間:2004-07-06 18:16:37 IP:219.95.xxx.xxx 未訂閱
    謝謝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

    發送簡訊給我
    #22 引用回覆 回覆 發表時間:2004-07-06 18:37:31 IP:211.20.xxx.xxx 未訂閱
    引言: 如把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;
    
    系統時間:2024-05-07 22:27:57
    聯絡我們 | Delphi K.Top討論版
    本站聲明
    1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
    2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
    3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!