2011-02-24 36 views
1

我有一個工作簿,其中幾個數據提要根據某些下拉菜單/用戶操作將參數傳遞迴SQL查詢。這可以保持工作簿的修剪,改進計算等 - 將所有項目級別的細節保存在工作簿中並不實際。excel vba:暫停參數化SQL查詢來完成?

我的VBA的一些元素依賴於來自這些參數化查詢的數據的評估。這就產生了這個問題 - 在評估宏中的所有內容之前,VBA不會等待參數傳遞迴查詢。

我很好奇,如果任何人有任何想法或建議的最佳做法,以編程方式暫停VBA執行,直到飼料刷新。我現在的工作是將我的VBA分爲兩部分,將取決於已更改數據的所有內容都放入單獨的函數中,並使用application.ontime暫停X秒。

Application.OnTime Now + TimeSerial(0, 0, 10), "Restart" 

這是一個90%的解決方案,但它並不理想。時間長度是任意的 - 在一個非常緩慢的連接上,它不夠長,在一個很快的連接上它不必要的緩慢。

理想情況下,會有某種方式等待Excel準備好然後繼續。使用MS上網的時候如何類似的控件庫,您可以使用

Do Until .document.ReadyState = "complete" 

暫停執行,直到IE返回就緒狀態。任何更優雅的解決方案的策略?

編輯:每低於喬恩,添加代碼,並解釋SQL查詢是如何工作的:

select sts1.studentid, sts1.alphascore as testcycle, 
sts2.numscore as lexile, sts3.alphascore as gleq, sts4.numscore as nce 

from ps.studenttestscore sts1 
join ps.students stu on (sts1.studentid = stu.id) 
join ps.studenttestscore sts2 on (sts1.studenttestid = sts2.studenttestid) 
join ps.studenttestscore sts3 on (sts1.studenttestid = sts3.studenttestid) 
join ps.studenttestscore sts4 on (sts1.studenttestid = sts4.studenttestid) 

where (stu.id = ?) and (sts1.testscoreid = 578) and (sts2.testscoreid = 575) 
and (sts3.testscoreid = 577) and (sts4.testscoreid = 576) 

的?是傳遞相關學生ID的參數 - MS查詢使用該參數的單元格值。它看起來的細胞只是還基於選擇了什麼樣的學生查找:

=IFERROR(INDEX(Stu!$B:$F,MATCH(Student!B2,Stu!$F:$F,0),1),999999) 

(在IFERROR只是傳遞一個任意數量,以防止討厭的對話框從,如果不正確的值在某種程度上被選中彈出) 。

+0

請你給一個更長的SQL調用和周邊代碼的例子 - 我不知道爲什麼它會等待執行。乾杯 – 2011-02-24 15:22:16

+0

目前還不清楚你是如何執行該SQL的 - 你能展示你的VBA代碼嗎?你到底用了什麼「數據饋送」? – 2011-02-24 17:19:49

回答

2

你的錯誤是使用MS-Query。使用ADODB編碼數據庫調用,並等待ADODB.Command對象的Execute方法。

...如果這就是你實際做的。這裏有一定的猜測,但看起來好像查詢的狀態 - 不是它嵌入的表單 - 是您需要的信息。

該代碼異步調用SQL查詢 - 它在概念上類似於命令對象,這是(我認爲)你實際上在做什麼 - 原始的'sleep'循環可以被進度條或代碼替換用於在其他地方投票標誌和計算。可能會造成ADO對象的狀態和狀態屬性混淆。通常,0表示關閉,1表示關閉(對於返回打開連接或數據集的對象),高於1的值對應於等待或執行。

您當然可以同步調用查詢。

我可以給你'DataConnection'的代碼,但你最好去ConnectionStrings.com。

 

Public Function FetchRecordSet(SQL As String, Optional CursorType As CursorTypeEnum = adOpenForwardOnly) As ADODB.Recordset 
On Error Resume Next 

Set FetchRecordSet = New ADODB.Recordset 

With FetchRecordSet 

    .CacheSize = 8 
    Set .ActiveConnection = DataConnection 
    .Open SQL, , CursorType, adLockReadOnly, adCmdText + adAsyncFetch 

    Do While .State > 1 
     Application.StatusBar = "Retrieving data... " 
     Sleep 250 
    Loop 

End With 

Application.StatusBar = False 

End Function 





[更新]

我已經學到了一些東西,因爲我張貼了這個答案:

如果你知道命令的名稱,rowset-返回函數或MS-Access數據庫中的命名查詢,請不要打擾如此調用它:

 

    SQL = "SELECT * FROM MyQuery" 
    .Open SQL, , CursorType, adLockReadOnly, adCmdText + adAsyncFetch 

打電話名字命令,並告訴數據庫引擎是使用adCmdStoredProc常數命名的命令:

 

    SQL = "MyQuery" 
    .Open SQL, , CursorType, adLockReadOnly, adCmdStoredProc + adAsyncFetch 

它運行得要快得多。

查一查MSDN上的CommandTypeEnum之中,並且使用任何最適合您:

https://msdn.microsoft.com/en-us/library/ms675946(v=vs.85).aspx

使用adCmdTable命名錶,看看是否可以工作比adCmdStoredProc的「視圖」對象更好 - 我我發現它在數據庫引擎之間有所不同。