VFP 愛用者社區 首頁 VFP 愛用者社區
本討論區為 Visual Foxpro 愛用者經驗交流的地方, 請多多利用"搜尋"的功能, 先查看看有無前例可循, 如果還有不懂的再發問. 部份主題有附加檔案, 須先註冊成為社區居民才可以下載.
 
 常見問題常見問題   搜尋搜尋   會員列表會員列表   會員群組會員群組   會員註冊會員註冊 
 個人資料個人資料   登入檢查您的私人訊息登入檢查您的私人訊息   登入登入

不需要MSCOMCTL.OCX的自制Select-SQL進度條
前往頁面 上一頁  1, 2, 3  下一頁
 
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區
上一篇主題 :: 下一篇主題  
發表人 內容
小賴



註冊時間: 2004-12-27
文章: 476


第 16 樓

發表發表於: 星期四 九月 05, 2013 2:53 am    文章主題: 引言回覆

直接使用Jerryclt原程式碼(一樓) 與CKP6250資料庫(6樓)實現每200筆顯示進度:

Select * From 傳票檔 ;
WHERE ((MOD(RECNO(), 200) = 1 OR RECNO() >= RECCOUNT() - 60) AND progress_bar(RECNO()*100/RECCOUNT(),'處理進度.... '+TRANSFORM(INT(RECNO()*100/RECCOUNT()))+'%') AND .F.);
OR (! DELETED() AND BETWEEN(Date ,'0901','0930')) INTO Cursor AA


簡化條件 (A AND B AND C) OR D

說明如下

A. (MOD(RECNO(), 200) = 1 OR RECNO() >= RECCOUNT() - 60) //每200筆或最後60筆才顯示
B. progress_bar(RECNO()* .... //顯示進度
C. .F.
D. WHERE 條件

X. (A AND B AND C) // 每200筆或最後60筆顯示進度並傳回.F. ; 只有當A = .F. 電腦才會判讀B
Y. X OR D //因為 X = .F. 所以 X OR D之結果為D 也就是WHERE 條件之結果
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件
jerryclt



註冊時間: 2009-03-10
文章: 334
來自: 佛心來的

第 17 樓

發表發表於: 星期四 九月 05, 2013 7:31 am    文章主題: 引言回覆

小賴 寫到:
~43 ~
A. (MOD(RECNO(), 200) = 1 OR RECNO() >= RECCOUNT() - 60) //每200筆或最後60筆才顯示
B. progress_bar(RECNO()* .... //顯示進度
C. .F.
D. WHERE 條件

X. (A AND B AND C) // 每200筆或最後60筆顯示進度並傳回.F. ; 只有當A = .F. 電腦才會判讀B
Y. X OR D //因為 X = .F. 所以 X OR D之結果為D 也就是WHERE 條件之結果


紅色部份是不是寫錯?

乍看之下好像真的會減少 progress_bar 執行的次數,
只不知 WHERE 子句的複雜化,會不會拖慢 SELECT-SQL,
小弟來試試先,
謝謝小賴兄的指點!
回頂端
檢視會員個人資料 發送私人訊息
ckp6250



註冊時間: 2004-07-30
文章: 1645


第 18 樓

發表發表於: 星期四 九月 05, 2013 7:56 am    文章主題: 引言回覆

不用測試,光用看的就看得出來
肯定拖慢 SELECT-SQL
因為,單是判斷第一個條件
MOD(RECNO(), 200) = 1
就必需掃描整個資料庫了,VFP的OPTIMIZE完全用不上
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
jerryclt



註冊時間: 2009-03-10
文章: 334
來自: 佛心來的

第 19 樓

發表發表於: 星期四 九月 05, 2013 8:45 am    文章主題: 引言回覆

大功告成 !!
原始碼已修正如下:

* 進度條函數
PROCEDURE progress_bar
LPARAMETERS val1
IF val1>0 AND val1<=100
  IF TYPE('ctln')#'O'
    PUBLIC ctln
    ctln=CREATEOBJECT('my_progress')
    ctln.show()
  ENDIF
  ctln.show_progress(INT(val1))
  IF val1>=100
    RELEASE ctln
  ENDIF
ENDIF
RETURN .F.
ENDPROC

* 自訂進度條視窗
DEFINE CLASS my_progress AS FORM
  AlwaysOnTop=.T.
  AutoCenter=.T.
  BorderStyle=2
  Caption=''
  Closable=.F.
  ControlBox=.F.
  Height=70
  MaxButton=.F.
  MinButton=.F.
  Movable=.F.
  Name='my_progress'
  ShowTips=.T.
  ShowWindow=1
  Width=350
  WindowType=0

  ADD OBJECT __OutUpLine AS line WITH;
    BorderWidth=1,;
    Height=0,;
    Left=4,;
    Top=4,;
    Width=342,;
    BorderColor=RGB(0,0,0),;
    ZOrderSet=3,;
    Name='__OutUpLine'

  ADD OBJECT __OutDownLine AS line WITH;
    BorderWidth=1,;
    Height=0,;
    Left=4,;
    Top=66,;
    Width=342,;
    BorderColor=RGB(255,255,255),;
    ZOrderSet=6,;
    Name='__OutDownLine'

  ADD OBJECT __OutLeftLine AS line WITH;
    BorderWidth=1,;
    Height=62,;
    Left=4,;
    Top=4,;
    Width=0,;
    BorderColor=RGB(0,0,0),;
    ZOrderSet=4,;
    Name='__OutLeftLine'

  ADD OBJECT __OutRightLine AS line WITH;
    BorderWidth=1,;
    Height=62,;
    Left=346,;
    Top=4,;
    Width=0,;
    BorderColor=RGB(255,255,255),;
    ZOrderSet=5,;
    Name='__OutRightLine'

  ADD OBJECT __InUpLine AS line WITH;
    Height=0,;
    Left=21,;
    Top=31,;
    Width=309,;
    BorderColor=RGB(0,0,0),;
    ZOrderSet=7,;
    Name='__InUpLine'

  ADD OBJECT __InDownLine AS line WITH;
    Height=0,;
    Left=21,;
    Top=59,;
    Width=309,;
    BorderColor=RGB(255,255,255),;
    ZOrderSet=10,;
    Name='__InDownLine'

  ADD OBJECT __InLeftLine AS line WITH;
    Height=28,;
    Left=21,;
    Top=31,;
    Width=0,;
    BorderColor=RGB(0,0,0),;
    ZOrderSet=8,;
    Name='__InLeftLine'

  ADD OBJECT __InRightLine AS line WITH;
    Height=29,;
    Left=330,;
    Top=31,;
    Width=0,;
    BorderColor=RGB(255,255,255),;
    ZOrderSet=9,;
    Name='__InRightLine'

  ADD OBJECT progress_title AS label WITH;
    Alignment=2,;
    AutoSize=.T.,;
    BackStyle=0,;
    Caption='處理進度... ',;
    FontName='細明體',;
    FontSize=14,;
    Height=25,;
    Left=114,;
    Top=9,;
    Width=122,;
    ZOrderSet=0,;
    Name='progress_title'

  ADD OBJECT progress_per AS Shape WITH;
    Top=35,;
    Left=25,;
    Height=20,;
    Width=0,;
    FillColor=RGB(0,0,255),;
    BorderStyle=0,;
    FillStyle=0,;
    SpecialEffect=0,;
    ZOrderSet=1,;
    Name='progress_per'

  * 顯示進度格與百分比
  PROCEDURE show_progress
    LPARAMETERS pt_per1
    WITH thisform
      .LockScreen=.T.
      .progress_title.caption='處理進度... '+TRANSFORM(pt_per1)+'%'
      .progress_per.width=pt_per1*3
      .LockScreen=.F.
    ENDWITH
*    WAIT WINDOW '' TIMEOUT 0.001 * 想看到完整1-100%就把 最左邊 * 拿掉
  ENDPROC
ENDDEFINE

* ---------- 實例 -----------
SELECT * FROM 傳票檔;
  WHERE (MOD(RECNO(),CEILING(RECCOUNT()/100))=0 OR RECNO()=RECCOUNT()) AND progress_bar(IIF(RECCOUNT()=0,100,RECNO()*100/RECCOUNT())) OR;
      (!DELETED() AND BETWEEN(Date,'0101','1231'));
  ORDER BY Date INTO CURSOR _tmpf
progress_bar(100)

本例在 199954 筆記錄中提取了 196470 筆, 耗時 0~1 秒,
進度條跑得很快,
想要完美呈現 1~100% 的過程又不怕拖慢速度的話,
就把上頭紅色那行的 * 拿掉!


多虧大家的提示,
尤其是最後小賴兄的MOD(),
真是天外一筆哪!
不過小弟不明白小賴兄那個 C (就是 AND .F.這句)的作用,
套上去會被濾掉一推記錄.


jerryclt 在 星期五 九月 06, 2013 1:07 pm 作了第 5 次修改
回頂端
檢視會員個人資料 發送私人訊息
jerryclt



註冊時間: 2009-03-10
文章: 334
來自: 佛心來的

第 20 樓

發表發表於: 星期四 九月 05, 2013 9:05 am    文章主題: 引言回覆

ckp6250 寫到:
不用測試,光用看的就看得出來
肯定拖慢 SELECT-SQL
因為,單是判斷第一個條件
MOD(RECNO(), 200) = 1
就必需掃描整個資料庫了,VFP的OPTIMIZE完全用不上


話雖是這樣說,
但是判斷RECCOUNT()次 MOD(RECNO(), 200) = 1,
肯定比呼叫RECCOUNT()次 progress_bar() 來得便宜,
而且不管怎樣下WHERE條件式,
SELECT-SQL一樣要掃瞄整個資料表格, 不是嗎!?

Garfield兄的 mint / mcount,
目的是要減少執行 show_progress 的次數(最多顯示100次,但是呼叫了progress_bar*RECCOUNT()次),
小賴兄把MOD()放進SELECT內,
更是省去呼叫 progress_bar 的次數(最多呼叫100次)...

如果還有更精簡的運算式,
請大家不吝提供...感恩啊!
回頂端
檢視會員個人資料 發送私人訊息
小賴



註冊時間: 2004-12-27
文章: 476


第 21 樓

發表發表於: 星期四 九月 05, 2013 10:09 am    文章主題: 引言回覆

TO jerryclt 兄

1. 請 Check 有(AND .F.) 和無 (AND .F.) 提取資料筆數差異

2. 如果有差異;表示你的資料少了或多了... 讓進度條動作的那些筆

即 MOD(RECNO(),CEILING(RECCOUNT()/100))=0 OR RECNO()=RECCOUNT()) = .T. 的時候
此時條件式為 (.T. AND progress_bar()) OR (!DELETED() AND BETWEEN(Date,'0101','1231'))

偏偏你的 progress_bar() 都傳回 .T.
所以條件式變為 (.T.) OR (!DELETED() AND BETWEEN(Date,'0101','1231'))
二條件作 OR ; 第一個條件已是 .T.

所以不論 (!DELETED() AND BETWEEN(Date,'0101','1231')) 的結果為何都會是 .T.

// 其實此情形電腦直接傳回 .T. 根本沒有判定 (!DELETED() AND BETWEEN(Date,'0101','1231'))

3. 結論:讓進度條動作的那些筆;不一定符合 (!DELETED() AND BETWEEN(Date,'0101','1231'))

4. 修正方式有二
A. 使用 (AND .F.)
B. progress_bar() 固定傳回 .F.


因為我沒改你的程式碼; 所以只能用 (AND .F.)
之所以用RECCOUNT() - ? 是想讓最後 98 % ; 99%在畫面停留久一點
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件
jerryclt



註冊時間: 2009-03-10
文章: 334
來自: 佛心來的

第 22 樓

發表發表於: 星期四 九月 05, 2013 12:50 pm    文章主題: 引言回覆

小弟最後POST的修正程式碼,
已經不用 C 條件式了,
只要該運算式計算出的值是 1-100 的整數,
就會呼叫 progress_bar !
至於 progress_bar 傳回 .T. 或 .F. 已經無關緊要,
因為小賴兄不是用了個 OR 嗎?
(.T. OR (.T.))=(.F. OR (.T.))

如果真的放上 AND .F.
對於條件 between(Date,'0101','1231') 是沒差,
因為該條件是全部資料檢索,
但是如果下的是:
between(Date,'0901','0930')
就會少了 89 筆...
回頂端
檢視會員個人資料 發送私人訊息
小賴



註冊時間: 2004-12-27
文章: 476


第 23 樓

發表發表於: 星期四 九月 05, 2013 5:34 pm    文章主題: 引言回覆

jerryclt 寫到:

至於 progress_bar 傳回 .T. 或 .F. 已經無關緊要,
因為小賴兄不是用了個 OR 嗎?
(.T. OR (.T.))=(.F. OR (.T.))



(.T. OR (.T.))=(.F. OR (.T.)) = (.T. OR (.F.)) = .T.

第三種情形也會取出資料 ;
會是你要的嗎 ?
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件
jerryclt



註冊時間: 2009-03-10
文章: 334
來自: 佛心來的

第 24 樓

發表發表於: 星期四 九月 05, 2013 5:54 pm    文章主題: 引言回覆

您說得對,
總是會有小三介入... @@"

還是固定讓 progress_bar 傳回 .F.
回頂端
檢視會員個人資料 發送私人訊息
ckp6250



註冊時間: 2004-07-30
文章: 1645


第 25 樓

發表發表於: 星期五 九月 06, 2013 9:57 am    文章主題: 引言回覆

若 Reccount()=0 時,就出槌啦,請修正一下
又,在某些情況下,若下完 select 指令,若不再加上 progress_bar(100) 的話,這個進度條不能自動關閉,這可能要考慮修正一下
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
jerryclt



註冊時間: 2009-03-10
文章: 334
來自: 佛心來的

第 26 樓

發表發表於: 星期五 九月 06, 2013 3:13 pm    文章主題: 引言回覆

已修正,
加上紅色部份應該就沒問題了!
回頂端
檢視會員個人資料 發送私人訊息
ckp6250



註冊時間: 2004-07-30
文章: 1645


第 27 樓

發表發表於: 星期五 九月 06, 2013 3:56 pm    文章主題: 引言回覆

我的意思是,下完 Select ...... into cursor _tmp 後
progress_bar(100) , 這一行應該要省略才對

跑完 select 應該要自動關閉進度條,而不需再多下一道指令去關它
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
jerryclt



註冊時間: 2009-03-10
文章: 334
來自: 佛心來的

第 28 樓

發表發表於: 星期六 九月 07, 2013 4:25 pm    文章主題: 引言回覆

ckp6250 寫到:
我的意思是,下完 Select ...... into cursor _tmp 後
progress_bar(100) , 這一行應該要省略才對

跑完 select 應該要自動關閉進度條,而不需再多下一道指令去關它


照理應該會執行到 RECNO()=RECCOUNT() 這個結果,
所以也就應該會如期關閉 progress_bar,
什麼情況下 RECNO()=RECCOUNT() 這段會被忽略了呢?
回頂端
檢視會員個人資料 發送私人訊息
ckp6250



註冊時間: 2004-07-30
文章: 1645


第 29 樓

發表發表於: 星期六 九月 07, 2013 5:34 pm    文章主題: 引言回覆

有 join 的情況

程式碼如下

Select Acc4.invent, Acc13.Date, Acc13.mount;
FROM Acc4 INNER Join Acc13 ;
ON Acc4.invent = Acc13.invent;
ORDER By Acc4.invent, Acc13.Date ;
WHERE (Mod(Recno(),Ceiling(Reccount()/100))=0 Or Recno()=Reccount()) And progress_bar(Recno()*100/Reccount()) ;
OR (!Deleted() And Between(Acc13.Date,'01/01','12/31'));
Into Cursor _tmpf
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
jerryclt



註冊時間: 2009-03-10
文章: 334
來自: 佛心來的

第 30 樓

發表發表於: 星期一 九月 09, 2013 8:06 am    文章主題: 引言回覆

ckp6250 寫到:
有 join 的情況

程式碼如下

Select Acc4.invent, Acc13.Date, Acc13.mount;
FROM Acc4 INNER Join Acc13 ;
ON Acc4.invent = Acc13.invent;
ORDER By Acc4.invent, Acc13.Date ;
WHERE (Mod(Recno(),Ceiling(Reccount()/100))=0 Or Recno()=Reccount()) And progress_bar(Recno()*100/Reccount()) ;
OR (!Deleted() And Between(Acc13.Date,'01/01','12/31'));
Into Cursor _tmpf


將 SELECT 改成
Select Acc4.invent, Acc13.Date, Acc13.mount;
FROM Acc4 LEFT Join Acc13 ;
ON Acc4.invent = Acc13.invent;
ORDER By Acc4.invent, Acc13.Date ;
WHERE (Mod(Recno(),Ceiling(Reccount()/100))=0 Or Recno()=Reccount()) And progress_bar(Recno()*100/Reccount()) ;
OR (!Deleted() And Between(Acc13.Date,'01/01','12/31'));
Into Cursor _tmpf

試試
回頂端
檢視會員個人資料 發送私人訊息
從之前的文章開始顯示:   
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區 所有的時間均為 台北時間 (GMT + 8 小時)
前往頁面 上一頁  1, 2, 3  下一頁
2頁(共3頁)

 
前往:  
無法 在這個版面發表文章
無法 在這個版面回覆文章
無法 在這個版面編輯文章
無法 在這個版面刪除文章
無法 在這個版面進行投票
無法 在這個版面附加檔案
無法 在這個版面下載檔案


Powered by phpBB © 2001, 2005 phpBB Group
正體中文語系由 phpbb-tw 維護製作