我有一个工作簿,其中我的几个数据源将参数传递回SQL查询,具体取决于某些下拉菜单/用户操作。这样可以保持工作簿的修剪,改进计算等 - 在工作簿中本地保留所有项目级别的详细信息是不切实际的。
我的VBA的某些元素依赖于对来自这些参数化查询的数据的评估。这里出现了问题 - 在评估宏中的所有内容之前,VBA不会等待参数传递回查询。
我很好奇是否有任何想法或建议有关以编程方式“暂停”VBA执行的最佳实践,直到Feed刷新为止。我现在的工作是将我的VBA分成两部分,将依赖于已更改数据的任何内容抛出到单独的函数中,并使用application.ontime暂停X秒。
Application.OnTime Now + TimeSerial(0, 0, 10), "Restart"
这是一个90%的解决方案,但它不太理想。时间长度是任意的 - 在非常慢的连接上它不够长,而在快速连接上则不必要地慢。
理想情况下,会有某种方式等待Excel准备就绪然后继续。与使用MS Internet Controls库时的方式类似,您可以使用
Do Until .document.ReadyState = "complete"
暂停执行,直到IE返回就绪状态。任何更优雅的解决方案策略?
每个jon下面的编辑,添加代码并解释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 :(得分:2)
您的错误是使用MS-Query。使用ADODB对数据库调用进行编码,并等待ADODB.Command对象的Execute方法。
......如果这就是你真正在做的事情。这里有一定程度的猜测,但看起来好像查询的状态 - 而不是它嵌入的表格 - 是你需要的信息。
这段代码异步调用一个SQL查询 - 它在概念上类似于一个命令对象,这是(我认为)你实际在做什么 - 原始的'sleep'循环可以用进度条代替,或代码为其他地方的投票标志和计算。
仅供参考,ADO对象的状态和状态属性可能会令人困惑。通常,零表示关闭,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
[更新]
自从我发布这个答案后,我学会了一些东西:
如果您知道命令的名称,行集返回函数或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
,看看对于'view'对象是否比adCmdStoredProc
效果更好 - 我发现它在数据库引擎之间有所不同。
[/更新]