我正在编写/维护一个 Excel VBA 应用程序,其中有多个 QueryTables 链接到 MS sql 服务器数据库。该应用程序的用户可以通过操作 Excel 文档上的各种 UI 控件来更改对每个表的 SQL 查询。
我在使用 QueryTables 时遇到的问题之一是使用了多线程。文档上的每个 QueryTable 都有一个原始状态,必须在运行查询后恢复该状态。例如,如果 QueryTable1 有一个基本查询
Select * from example_table
并且用户在控件上选择了某些输入来创建
Select * from example_table Where object_oid = '10'
我需要恢复原始状态。下面的代码是我目前如何完成此任务的快照
Sub RefreshDataQuery()
'Dependencies: Microsoft Scripting Runtime (Tools->References) for Dictionary (HashTable) object
Dim querySheet As Worksheet
Dim interface As Worksheet
Set querySheet = Worksheets("QTable")
Set interface = Worksheets("Interface")
Dim sh As Worksheet
Dim qt As QueryTable
Dim qtDict As New Scripting.Dictionary
Set qtDict = UtilFunctions.CollectAllQueryTablesToDict
Set qt = qtDict.Item("Query from fred2")
''' Building SQL Query String '''
Dim sqlQueryString As String
Dim originalQueryCache As String
originalQueryCache = qt.CommandText
sqlQueryString = qt.CommandText
QueryBuilder.BuildSQLQueryStringFromInterface interface, sqlQueryString
MsgBox sqlQueryString
qt.CommandText = sqlQueryString
If Not qt Is Nothing Then
qt.Refresh
Else
'Error Messages and handling here
' Cut out to keep code short
End If
''' CLEAN UP '''
'Restore the original base SQL query
' Problem is here
' This, or any other altering statement, will error out if the query is still refreshing
qt.CommandText = originalQueryCache
' Other original state restoring code below...
' Free the dictionary
Set qtDict = Nothing
End Sub
理想情况下,如果我用另一种现代语言编写此代码,我将创建一个回调函数或在我自己的线程中使用完成通知程序运行刷新。我花了很多时间研究如何为 qt.Refresh 调用获取回调函数,但没有运气。我意识到我可以稍微“破解”这个问题,但我宁愿不从事不良做法,因为将来很多人将不得不保持这种做法。
此应用程序必须支持 Excel 2010 及更高版本
那么如何为在不同线程中运行的 VBA 函数创建回调函数呢?或者,我应该考虑另一种方法吗?