vba - 从 VBA 触发计算时,#GETTING_DATA 消息永远不会解析

标签 vba excel cube

我正在尝试将多维数据集函数的范围级刷新构建到一个基于多维数据集公式的大型工作簿中,因为当整个工作簿被刷新(小时和小时)时,这些函数的批处理在可用的多维数据集上总是执行得非常糟糕等待)。

我尝试使用的代码非常简单:

Public Sub RefreshRange()
    Dim rngTarget As Excel.Range
    Dim lngRescue As Long
    Dim blnCalcCheck As Boolean

    Set rngTarget = Selection
    Do
        rngTarget.Dirty
        rngTarget.Calculate
        DoEvents               '' Used reluctantly in case VBA blocks the event that
                               '' causes a recalc
        blnCalcCheck = blnCalcCheck Or ThisWorkbook.Connections("MyConnection").OLEDBConnection.Refreshing
        lngrescue = lngRescue + 1
        Sleep 200              '' API sleep function. Also tried Application.Wait.
        If lngRescue >= 200 Then Debug.Assert False

    Loop Until Not fblnIsGettingData(rngTarget) '' This function doesn't do much that 
                                                '' could break things. Just evaluates
                                                '' a formula for rngTarget that checks
                                                '' if any of the cells read 
                                                '' #GETTING_DATA

End Sub

这行不通。公式计算,解析为 #GETTING_DATA,但连接从未开始收集要放入其中的数据的过程。这只是开始,如果我有不同程度的可靠性

  • 手动重新计算工作表 (Shift-F9)。这在大约 50% 的时间有效。
  • 手动重新计算整个工作簿。这在大约 80% 的时间都有效。
  • 将计算模式设置为自动。这始终有效(到目前为止),但始终是工作簿级别。

如果我调用 Application.CalculateUntilAsyncQueriesDone,它也可能开始工作,但我不确定,因为这显然是一个工作簿级别的函数,更重要的是,我的工作簿似乎一直崩溃(我'我猜是因为我在常用名称中使用 UDF,但不确定)。

有谁知道如何手动触发启动该范围的整个“运行后台查询”消息的任何事件?或者,我如何观察 Excel.Exe 进程以找出它并可能通过 API 触发相同的东西?

最佳答案

这不起作用的原因是,无论出于何种原因,触发异步连接以使用立方体值公式获取数据的后计算事件在 VBA 运行时无法触发。这包括调用 DoEvents 的 VBA(因此上面的代码不起作用)。

但是,事件已安排并触发 - 一次,无论调用了多少次 Calculate - 一旦 VBA 完成它正在做的任何事情。这使得编码变得复杂,但并非不可能,通过使用计时器(我最终选择了 Application.OnTime 以便能够轻松地对所有内容进行分类,但是 API SetTimer也可能会工作。解决问题的一个非常简单的方法是(这里可能有错误,因为我真的不习惯使用静态):

Public Static Sub DoCalcEvery(Optional strInterval As String = vbNulLString, Optional wksTarget As Excel.Worksheet, blnContinue As Boolean = True)
    Dim strInterval_Inner As String
    Dim wksTarget_Inner as Excel.Worksheet
    Dim blnContinue_Inner As Boolean
    Dim lngCalcCount As Long
    Dim datNewCalcTime As Date
    Dim datPreviousCalcTime As Date

    '' Update static values if any new arguments provided
    '' Stopping is a little tricky too - hence blnContinue
    If strInterval <> vbNullString Then strInterval_Inner = strInterval
    If Not wksTarget Is Nothing Then Set wksTarget_Inner = wksTarget
    If lngCalcCount = 0 Then 
        blnContinue_Inner = blnContinue
    ElseIf blnContinue <> True Then
        blnContinue_Inner = False
    End If

    '' Clear out any previous OnTime instances
    '' This frequently (always?) errors, but looks like it is usually wrapped in 
    '' On Error elsewhere, so guessing in THIS specific case, the error is safely
    '' ignored.
    On Error Resume Next
    Application.OnTime datPreviousCalcTime, "DoCalcEvery", , False
    On Error Goto 0

    wksTarget.Calculate
    lngCalcCount = lngCalcCount + 1
    If blnContinue_Inner Then
        datNewCalcTime = Now + CDat(strInterval)
        Application.OnTime datNewCalcTime, "DoCalcEvery"
        datPreviousCalcTime = datNewCalcTime
    Else
        Debug.Print "Calculation complete. " & lngCalcCount & " iterations before stopped."
    End If
End Sub

这应该有效,并允许您在任意时间调用 DoCalcEvery 以停止计算。但是,如果使用这种方法,如果您不熟悉 OnTime,则需要牢记一些事项:

  • OnTime 在整个 Excel session 期间有效,除非被取消 这意味着如果您让 Excel 运行超过 24 小时,预计宏会再次触发。我被告知,为了达到效果,这甚至可能打开关闭的工作簿,所以请注意。不过,当 Excel 关闭时,OnTime 事件将失效。
  • 这意味着如果您通过单击停止、在 VBA 中其他地方出现错误或通过其他方式暂停代码,您将无法知道当前安排了哪些 OnTime 事件(如果有人知道如何找到它,我很想知道)

但是,考虑到这些附带条件,这种方法将允许触发正确的事件以启动多维数据集功能。当然,检测它们何时完成是完全不同的事情。

关于vba - 从 VBA 触发计算时,#GETTING_DATA 消息永远不会解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22223354/

相关文章:

c# - 如何从 Excel 中获取范围(打印区域)?

opengl - 在opengl中绘制体素(立方体)的最有效方法是什么?

http - 在没有直接数据库连接的情况下跨域访问 SSAS 多维数据集

ms-access - 在 VBA 中获取属性值

events - 未使用 adAsyncExecute 参数触发 ExecuteComplete ADODB 连接事件

excel - 如何查看数组中的项目

vba - 使用宏/vba 将多行从一个工作表复制到另一工作表

vba - 用于在工作表名称更改时更改 VBA 的动态 VBA 代码

c# - Excel 导入的 SQL 注入(inject)漏洞

具有不同 ID 的多维数据集的 Oracle SQL 分组