在VBA中评估()

时间:2013-07-05 08:37:15

标签: vba excel-vba debugging expression-evaluation excel

嗨,欢迎来到Evaluate()之谜

<小时/> MSDN Office开发人员参考(2013)文档说:

  

使用方括号(例如,“[A1:C5]”)与调用相同   带有字符串参数的Evaluate方法。


所以,我运行了一个非常简单的代码来查看Microsoft's Documentation of the Evaluate()方法的准确性。
毫不奇怪,我得到了一个奇怪的,虽然一致的结果 注意: 执行Immediate Window CTRL + G 中的4个命令。查看每个电话的差异。请注意内置的 错误 ,其中 显示每个MsgBox两次 。记住这一点,不要混淆......
将此代码粘贴在模块中

Private Sub SleepESub()
    Application.Wait Now + TimeValue("0:00:20")
    MsgBox "w8'd "
End Sub

然后在立即窗口中执行这4个命令(每次1个)

? Evaluate ("SleepESub()")
? [SleepESub()]
? [SleepESub]
? SleepESub

前2个立即执行代码;对我来说意味着他们已经评估了代码。第三个(根据文档)应该是 Evaluating ,但它的行为与在模块的主体中​​的行为方式不同< / em>的。立即窗口给出一个Error 2023但是来自模块体内的同一个调用就像你调用一个sub一样执行它。它等待 20 seconds 就好像它是一个正常Call SleepESub()这是4号电话。

任何人都能解释我在这里缺少的东西吗?第3行不是正确的Evaluation电话吗?或者它是否评估对sub本身的调用(如果这是有意义的)


更新:
我认为有些人误解了我在这里评估的内容 - 不要担心这是一个高级主题,我不是一个书作家,你不是读者。 (原谅我......
为了更好地了解您可以比较即时窗口与模块正文的结果。试试这段代码:

' Run each of the calls separately
' in a module's body and compare it with 
' the previous calls from the Immediate Window
    Sub ModuleBody()
        Evaluate ("SleepESub()")
        '[SleepESub()]
        '[SleepESub]
        'SleepESub
    End Sub

2 个答案:

答案 0 :(得分:6)

在我看来,执行代码的不同方式的不同之处在于它运行的线程 - UI线程或后台线程,以及解析器。对于显式定义的函数,Evaluate执行的函数的处理方式不同,从立即窗口调用的函数的处理方式也略有不同。

在:

Sub ModuleBody()
    Evaluate ("SleepESub()")
    [SleepESub()]
    [SleepESub]
    SleepESub
End Sub

Evaluate ("SleepESub()")[SleepESub()]似乎期待一个公式,Private Sub SleepESub()根本没有被执行。

根据解析器处理过程的方式,每个命令可以在单个线程中按顺序执行,导致Application.Wait的延迟,或者Application.Wait可能被认为仅有效在UI线程上,并在后台线程上运行时跳过。

这可以通过以下代码确认,由立即窗口中的?[SleepESub()]?Evaluate("SleepESub()")执行:

Private Declare PtrSafe Sub sapiSleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)
Private Sub SleepESub()
    'Application.Wait Now + TimeValue("0:00:05")
    sapiSleep 5000
    MsgBox "w8'd "
End Sub

使用sapiSleep 5000 API调用时,会发生等待(两次! - 提到的错误),但使用Application.Wait Now + TimeValue("0:00:05")时,不会发生延迟。

答案 1 :(得分:-1)

我认为说第3次调用没有评估是错误的:它确实评估了提供的对象,并返回其值(如文档所述)。

我稍微修改了Sub来说明:

Private Function SleepESub()
    Debug.Print Application.Wait(Now + TimeValue("0:00:02"))
    MsgBox "w8'd "
    SleepESub = 42
End Function

4次评估调用中的每次都会按预期返回42次。

不同的是:

  • 应用程序上下文(在一种情况下调用Application.Wait 成功,在另一个失败 - 注意调试输出 返回true或false)
  • 对例行程序的调用次数(一次或两次调用)

但我对这两种差异没有任何解释。