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

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



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

第 1 樓

發表發表於: 星期二 九月 03, 2013 10:39 am    文章主題: 不需要MSCOMCTL.OCX的自制Select-SQL進度條 引言回覆

轉自梅子論壇 http://www.mzvfp.com/read.php?tid=45337
原始碼:
引言回覆:
SET TALK OFF

cTable = GETFILE("dbf")
IF EMPTY(cTable)
RETURN .T.
ENDIF

SELECT * FROM (cTable) WHERE Progress_Bar( RECNO()*100/RECCOUNT(), "Processing ..."+STR(RECNO()*100/RECCOUNT())+"%" )

SET MESSAGE TO
CLOSE ALL
RELEASE ALL

* *************************************************************************
PROCEDURE progress_bar
LPARAMETERS tnUpdateValue, tcTitle
IF INT(tnUpdateValue) >= 1
IF TYPE( "oThre" ) <> "O"
PUBLIC oThre
oThre = CREATEOBJECT("frmProgress")
oThre.Show( )
ENDIF
oThre.ShowThre( tnUpdateValue, tcTitle )
IF INT( tnUpdateValue ) >= 100
= MESSAGEBOX( "Finished!", 64, "Info" )
RELEASE oThre
ENDIF
ENDIF
ENDPROC



* ***********************************************
DEFINE CLASS frmprogress AS FORM


DoCreate = .T.
ShowTips = .T.
AutoCenter = .T.
Caption = ""
ControlBox = .F.
Closable = .F.
MaxButton = .F.
MinButton = .F.
Movable = .F.

Height = 72
Width = 350
BorderStyle = 2
WindowType = 0
Name = "frmProgress"

ADD OBJECT line1 AS line WITH ;
BorderWidth = 2, ;
Height = 0, ;
Left = -1, ;
Top = 1, ;
Width = 348, ;
BorderColor = RGB(128,128,128), ;
ZOrderSet = 0, ;
Name = "Line1"


ADD OBJECT labthre AS label WITH ;
Alignment = 2, ;
Caption = "", ;
Height = 17, ;
Left = 48, ;
Top = 12, ;
Width = 288, ;
ZOrderSet = 1, ;
Name = "labThre"


ADD OBJECT line2 AS line WITH ;
BorderWidth = 2, ;
Height = 0, ;
Left = 2, ;
Top = 71, ;
Width = 346, ;
BorderColor = RGB(255,255,255), ;
ZOrderSet = 2, ;
Name = "Line2"


ADD OBJECT line3 AS line WITH ;
BorderWidth = 2, ;
Height = 68, ;
Left = 1, ;
Top = 1, ;
Width = 0, ;
BorderColor = RGB(128,128,128), ;
ZOrderSet = 3, ;
Name = "Line3"


ADD OBJECT line4 AS line WITH ;
BorderWidth = 2, ;
Height = 68, ;
Left = 349, ;
Top = 2, ;
Width = 0, ;
BorderColor = RGB(255,255,255), ;
ZOrderSet = 4, ;
Name = "Line4"


ADD OBJECT image1 AS image WITH ;
Picture = "progress.bmp", ;
BackStyle = 0, ;
Height = 32, ;
Left = 7, ;
Top = 7, ;
Width = 32, ;
ZOrderSet = 5, ;
Name = "Image1"

ADD OBJECT olethre AS OleControl WITH ;
OleClass = "MSComctlLib.ProgCtrl.2", ;
Top = 45, ;
Left = 14, ;
Height = 13, ;
Width = 326, ;
ZOrderSet = 6, ;
Name = "oleThre"


ADD OBJECT line5 AS line WITH ;
Height = 0, ;
Left = 9, ;
Top = 61, ;
Width = 333, ;
BorderColor = RGB(255,255,255), ;
ZOrderSet = 7, ;
Name = "Line5"


ADD OBJECT line7 AS line WITH ;
Height = 0, ;
Left = 9, ;
Top = 41, ;
Width = 333, ;
BorderColor = RGB(128,128,128), ;
ZOrderSet = 8, ;
Name = "Line7"


ADD OBJECT line8 AS line WITH ;
Height = 19, ;
Left = 9, ;
Top = 42, ;
Width = 0, ;
BorderColor = RGB(128,128,128), ;
ZOrderSet = 9, ;
Name = "Line8"


ADD OBJECT line6 AS line WITH ;
Height = 19, ;
Left = 341, ;
Top = 42, ;
Width = 0, ;
BorderColor = RGB(255,255,255), ;
ZOrderSet = 10, ;
Name = "Line6"


*-- Used to show the thremeter progress
PROCEDURE showthre
LPARAMETERS tnProgress, tcTitle
LOCAL lnProgress, lcTitle
lnProgress = INT(tnProgress)
IF PARAMETERS()=2
lcTitle = tcTitle
ELSE
lcTitle = ""
ENDIF
WITH thisform
.LockScreen = .T.
.labThre.Caption=lcTitle
.oleThre.Value=lnProgress
.LockScreen = .F.
ENDWITH
ENDPROC


ENDDEFINE



原本在自己的電腦上套用是可行的,
就開始大改特改一堆程式碼,
結果送到客戶那兒,
出現了不預知的錯誤......就是客戶端沒那個該死的MSCOMCTL.OCX

小弟修改了一些程式段後已無MSCOMCTL.OCX的需求了,
以下將修改過的程式碼提供狐友們參考,
如有待改進的地方也請不吝指教...

PROCEDURE progress_bar
LPARAMETERS val1,pt_title1
IF val1>0 AND val1<=100
  IF TYPE('ctln')#'O'
    PUBLIC ctln
    ctln=CREATEOBJECT('my_progress')
    ctln.show()
  ENDIF
  ctln.show_progress(INT(val1),pt_title1)
  IF val1=100
    RELEASE ctln
  ENDIF
ENDIF
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,pt_title1
    LOCAL pt_per2,pt_title2
    pt_per2=INT(pt_per1)
    pt_title2=IIF(PARAMETERS()=2,pt_title1,'')
    WITH thisform
      .LockScreen=.T.
      .progress_title.caption=pt_title2
      .progress_per.width=pt_per2*3
      .LockScreen=.F.
    ENDWITH
  ENDPROC
ENDDEFINE


實例:
* ---------- 在 Select-SQL 內的寫法
SELECT * FROM table;
  WHERE field='' AND;
   !DELETED() AND progress_bar(RECNO()*100/RECCOUNT(),'處理進度... '+RIGHT(STR(INT(RECNO()*100/RECCOUNT())),3)+'%');
   INTO CURSOR _tmpf
progress_bar(100,'處理進度... '+'100%')
IF _TALLY>0
  * ---------- 逐筆的寫法
  SELECT _tmpf
  _nCount=RECCOUNT()
  GO TOP
  DO WHILE !EOF()
    progress_bar(RECNO()*100/_nCount,'處理進度... '+RIGHT(STR(INT(RECNO()*100/_nCount)),3)+'%')
    SELECT _tmpf
    SKIP
  ENDDO
  progress_bar(100,'處理進度... '+'100%')
  SELECT _tmpf
  USE IN _tmpf
ENDIF
回頂端
檢視會員個人資料 發送私人訊息
ckp6250



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


第 2 樓

發表發表於: 星期二 九月 03, 2013 2:42 pm    文章主題: 引言回覆

用 RecNo() 來做會不會有問題呀?
如果這個 Select 有加上 order by 或者 group by 或者是 join 的話

其次,若資料量很大,比如數十萬筆中要取出一千筆的話,
這個 where 語句會不會拖慢效率呢?
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
jerryclt



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

第 3 樓

發表發表於: 星期二 九月 03, 2013 4:04 pm    文章主題: 引言回覆

事實上我自己的SORUCE裡是這樣:
SELECT * FROM oo01 RIGHT OUTER JOIN oo01a ON or01a_001=or01_001;
  WHERE !EMPTY(or01_001) AND or01_016=.F. AND TRANSFORM(or01_006)>=TRANSFORM(&_bproc.10.value) AND;
      TRANSFORM(or01_006)<=TRANSFORM(&_bproc.11.value) AND or01_003=ALLTRIM(&_bproc.12.value) AND;
      EMPTY(or01a_009) AND or01a_002=ALLTRIM(&_bproc.13.value) AND !DELETED() AND;
      progress_bar(RECNO()*100/RECCOUNT(),'處理進度... '+RIGHT(STR(INT(RECNO()*100/RECCOUNT())),3)+'%');
  ORDER BY or01_001 DESC INTO CURSOR _tmpor
progress_bar(100,'處理進度... '+'100%')

既有JOIN又有ORDER BY還有DESC,
但是PROGRESS並不會變成由100到0的方式顯示,
因為RECNO() / RECCOUNT()是指向 CURSOR _tmpor 吧!

至於資料量大的話,
有哪一種 progress 不會拖慢 SELECT 呢?
用 timer 嗎?
回頂端
檢視會員個人資料 發送私人訊息
ckp6250



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


第 4 樓

發表發表於: 星期二 九月 03, 2013 4:50 pm    文章主題: 引言回覆

試了一下,給您按一個讚!
若大資料量時,我試了廿萬筆,實在很慢,但這不是您的問題
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
jerryclt



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

第 5 樓

發表發表於: 星期二 九月 03, 2013 5:17 pm    文章主題: 引言回覆

剛剛實測了一下,
從 72184(tt0) + 123724(tt1) 筆記錄內,
SELECT * FROM tt0 RIGHT OUTER JOIN tt1 ON st01a_001=st01_001;
WHERE (st01_001='KO' OR st01_001='CA' OR st01_001='BZ') AND st01_006<{^1980.01.01} AND st01a_002='9' AND;
st01a_007>={^2001.01.01} AND st01a_007<={^2012.06.30} AND !DELETED() AND;
progress_bar(RECNO()*100/RECCOUNT(),'處理進度... '+RIGHT(STR(INT(RECNO()*100/RECCOUNT())),3)+'%');
ORDER BY st01_006 DESC INTO CURSOR _tmpf
抽出594筆,只花了..... 2 秒
回頂端
檢視會員個人資料 發送私人訊息
ckp6250



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


第 6 樓

發表發表於: 星期二 九月 03, 2013 5:39 pm    文章主題: 引言回覆

我傳一個檔,您試一下,指令如下
代碼:

Select * From 傳票檔 ;
      WHERE !Deleted() And ;
      BETWEEN(Date ,'0901','0930') And ;
      progress_bar(RECNO()*100/RECCOUNT(),'處理進度.... '+TRANSFORM(INT(RECNO()*100/RECCOUNT()))+'%');      
      INTO Cursor _tmpf


1.它不會由 1% 起跳,會從66%起跳
2.如果把日期範圍放大,比如設成BETWEEN(Date ,'0101','1231'),那麼,有加progress_bar和沒加progress_bar,速度差了幾百倍
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
jerryclt



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

第 7 樓

發表發表於: 星期三 九月 04, 2013 7:18 am    文章主題: 引言回覆

測試結果...確實是由 66% 起, 73% 結束,
由此可證明 progress_bar 不是針對 CURSOR 作反應(小弟上文說的是錯誤);
話又說回來,
如果資料表格只有一筆記錄,
把一筆記錄拆分為1~100%的進度條,
也是很詭異的一件事,不是嗎?
所以小弟暫且不去計較每次的進度條都得從1而終 ^^"

另外...實測計時如下:
BETWEEN(Date ,'0901','0930')---->1-2秒
BETWEEN(Date ,'0101','1231')---->10-11秒
沒差到幾百倍吧 @@"

還有一個重點,
就算改成 BETWEEN(Date ,'0101','1231')
如果拿掉 progress_bar 耗時不到1秒,
不到1秒的 query 可以考慮不使用 progress_bar
小弟目前大部份只應用在
  * ---------- 逐筆的寫法
  SELECT _tmpf
  _nCount=RECCOUNT()
  GO TOP
  DO WHILE !EOF()
    progress_bar(RECNO()*100/_nCount,'處理進度... '+RIGHT(STR(INT(RECNO()*100/_nCount)),3)+'%')
    SELECT _tmpf
    SKIP
  ENDDO
  progress_bar(100,'處理進度... '+'100%')
這種場合比較多


jerryclt 在 星期三 九月 04, 2013 11:41 am 作了第 2 次修改
回頂端
檢視會員個人資料 發送私人訊息
garfield
Site Admin


註冊時間: 2003-01-30
文章: 2160


第 8 樓

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

如果改進成最多只顯示100次, 顯示速度會快很多,

Define Class my_progress As Form
......
WindowType=0
加上一行
mint = -1
****
Procedure show_progress
.........
pt_per2=Int(pt_per1)
加上這5行
IF pt_per2 =this.mint
RETURN
ELSE
this.mint = pt_per2
endif

_________________
利用>>搜尋<<的功能會比問的還要快得到答案.
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件
ckp6250



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


第 9 樓

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

1.這正是我先前提的,用RecNo()會有問題.
2.我指的差百倍,是指設成BETWEEN(Date ,'0101','1231') 時,有加和沒加progress_bar時的差異,您的差異小,可能是您的電腦的規格強,我的是10年前的NB,沒加progress_bar時,同樣是不到一秒;有加時,可就天荒地老了,但,我們也不能事先知道,使用者用的是那一個等級的電腦
3.『不到1秒的 query 可以考慮不使用 progress_bar 』這句話當然沒錯,問題是一個函數要運用到很多的 Select 場合,事先根本無法預測它會跑多久。
4.我個人的想法,加到 Where 後的方式,實在會影響效能,尤其是老一點的電腦,如果改用Timer,再加上 garfield 的建議,也許會好一點
5.既然叫做『進度條』就得名實相符,要從一而終,否則,不如改個名稱和呈現方式,免得被說是廣告不實^^
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
小賴



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


第 10 樓

發表發表於: 星期三 九月 04, 2013 11:27 am    文章主題: 引言回覆

ckp6250 寫到:

Select * From 傳票檔 ;
WHERE !Deleted() And ;
BETWEEN(Date ,'0901','0930') And ;
progress_bar(RECNO()*100/RECCOUNT(),'處理進度.... '+TRANSFORM(INT(RECNO()*100/RECCOUNT()))+'%');
INTO Cursor _tmpf
[/code]

1.它不會由 1% 起跳,會從66%起跳



不知 WHERE BETWEEN(Date ,'0901','0930') And progress_bar
改成 WHERE progress_bar AND BETWEEN(Date ,'0901','0930')
或 BETWEEN(Date ,'0901','0930') OR progress_bar
是否可成

記得 A AND B
當 A = .F. 時好像不會判斷B
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件
jerryclt



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

第 11 樓

發表發表於: 星期三 九月 04, 2013 12:37 pm    文章主題: 引言回覆

小賴兄是對的
把 progress 放在 WHERE 後第一個判斷式,
就會顯示全進度條,
缺點是速度變慢了,
另外...不可以用OR, 因為...其他條件式都變成無效!

下午再來試試 Garfield 兄的方式
回頂端
檢視會員個人資料 發送私人訊息
garfield
Site Admin


註冊時間: 2003-01-30
文章: 2160


第 12 樓

發表發表於: 星期三 九月 04, 2013 1:48 pm    文章主題: 引言回覆

不用recno() 改用count會比較準,
假設會處理全部的資料,
執行時改用
progress_bar(RECC() ,'處理進度.... ')
*****
程式碼要修正
Define Class my_progress As Form
......
WindowType=0
加上2行
mint = -1
mcount = 0
****
Procedure show_progress
.........
pt_per2=Int(pt_per1)
改成
this.mcount = this.mcount + 1
pt_per2=Int( this.mcount*100 / pt_per1)

加上這5行
IF pt_per2 =this.mint
RETURN
ELSE
this.mint = pt_per2
endif

_________________
利用>>搜尋<<的功能會比問的還要快得到答案.
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件
jerryclt



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

第 13 樓

發表發表於: 星期三 九月 04, 2013 2:00 pm    文章主題: 引言回覆

剛剛測了一下 Garfield 兄早先的方式
IF pt_per1=this.mint
RETURN
ELSE
this.mint=pt_per1
ENDIF
WAIT WINDOW pt_per1 TIMEOUT 1   * 加了這一行
實際有從1跑到99%,
只是進度條 REFRESH 速度不夠快而已
回頂端
檢視會員個人資料 發送私人訊息
jerryclt



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

第 14 樓

發表發表於: 星期三 九月 04, 2013 5:25 pm    文章主題: 引言回覆

Garfield兄,
測試有mcount的結果和沒有mcount的結果是一樣的,
除非加上 wait window '' timeout 0.05
不然進度條都是跳著跑
回頂端
檢視會員個人資料 發送私人訊息
ckp6250



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


第 15 樓

發表發表於: 星期三 九月 04, 2013 9:59 pm    文章主題: 引言回覆

百尺竿頭,更進一步
精益求精,加油!
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
從之前的文章開始顯示:   
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區 所有的時間均為 台北時間 (GMT + 8 小時)
前往頁面 1, 2, 3  下一頁
1頁(共3頁)

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


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