1

我有一个工作簿,其中我的几个数据提要根据一些下拉菜单/用户操作将参数传递回 SQL 查询。这可以保持工作簿修剪、改进计算等 - 将所有项目级详细信息本地保存在工作簿中是不切实际的。

我的 VBA 的某些元素取决于对来自这些参数化查询的数据的评估。这里出现了问题 - VBA 在评估宏中的所有内容之前不会等待参数被传递回查询。

我很好奇是否有人对以编程方式“暂停”VBA 执行直到提要刷新的最佳实践有任何想法或建议。我现在的工作是将我的 VBA 分成两部分,将依赖于更改数据的任何内容放入单独的函数中,然后使用 application.ontime 暂停 X 秒。

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

这是一个 90% 的解决方案,但并不理想。时间长度是任意的——在一个非常慢的连接上它不够长,而在一个快速的连接上它是不必要的慢。

理想情况下,会有某种方式等到 Excel 准备好然后继续。类似于使用 MS Internet 控件库时可以使用的方式

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 只是向上传递一个任意数字,以防止在以某种方式选择了不正确的值时弹出讨厌的对话框)。

4

1 回答 1

2

您的错误是使用 MS-Query。使用 ADODB 对数据库调用进行编码,然后等待 ADODB.Command 对象的 Execute 方法。

...如果那是您实际在做的事情。这里有一定的猜测,但看起来查询的状态 - 而不是它嵌入的工作表 - 是您需要的信息。

此代码异步调用 SQL 查询 - 它在概念上类似于命令对象,这是(我认为)您实际在做的事情 - 粗略的“睡眠”循环可以替换为进度条或轮询标志的代码和其他地方的计算。

仅供参考,ADO 对象的状态和状态属性可能会令人困惑。通常,0 表示关闭,1 表示打开(对于返回打开连接或数据集的对象),大于 1 的值对应于等待或执行。

当然,您可以只同步调用查询。

我可以为您提供“DataConnection”的代码,但您最好访问 ConnectionStrings.com。

公共函数 FetchRecordSet(SQL As String, Optional CursorType As CursorTypeEnum = adOpenForwardOnly) As ADODB.Recordset
出错时继续下一步

设置 FetchRecordSet = New ADODB.Recordset

使用 FetchRecordSet

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

    Do While .State > 1
        Application.StatusBar = "正在检索数据..."
        睡眠 250
    环形

结束于

Application.StatusBar = False

结束功能





[更新]

自从发布此答案以来,我学到了一些东西:

如果您知道 MS-Access 数据库中的命令、行集返回函数或命名查询的名称,请不要像这样调用它:

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

按名称调用命令,并使用adCmdStoredProc常量告诉数据库引擎这是一个命名命令:

    SQL = "我的查询"
    .Open SQL, , CursorType, adLockReadOnly, adCmdStoredProc + adAsyncFetch

它运行得非常快。

在 MSDN 上查找 CommandTypeEnum,并使用最适合您的方式:

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

用于 adCmdTable命名表,看看它是否比adCmdStoredProc“视图”对象更有效——我发现它在数据库引擎之间有所不同。

[/更新]

于 2011-03-08T16:23:17.640 回答