  | 
				VFP 愛用者社區 本討論區為 Visual Foxpro 愛用者經驗交流的地方, 請多多利用"搜尋"的功能, 先查看看有無前例可循, 如果還有不懂的再發問. 部份主題有附加檔案, 須先註冊成為社區居民才可以下載.   
				 | 
			 
		 
		 
	
		| 上一篇主題 :: 下一篇主題   | 
	 
	
	
		| 發表人 | 
		內容 | 
	 
	
		小賴
 
 
  註冊時間: 2004-12-27 文章: 477
 
  第 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 文章: 477
 
  第 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 文章: 477
 
  第 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
 
 
試試 | 
			 
		  | 
	 
	
		| 回頂端 | 
		 | 
	 
	
		  | 
	 
	
		 | 
	 
 
  
  	 
	    
  	   | 
 	
您 無法 在這個版面發表文章 您 無法 在這個版面回覆文章 您 無法 在這個版面編輯文章 您 無法 在這個版面刪除文章 您 無法 在這個版面進行投票 您 無法 在這個版面附加檔案 您 無法 在這個版面下載檔案
  | 
   
  
		 |