Evaluate() in VBA

后端 未结 2 586
谎友^
谎友^ 2020-12-29 14:41

Hi and welcome to the Evaluate() mystery


The MSDN Office Developer Reference (2013) Documentation says:

Using square brackets (for example, \

相关标签:
2条回答
  • 2020-12-29 15:34

    I think that it is wrong to state that the 3rd call is not evaluating : it does indeed evaluate the provided object, and return its value (as documented).

    I have slightly modified the Sub to illustrate:

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

    Each of the 4 evaluation calls will indeed return 42 as expected.

    What is different is:

    • the application context (in one case the call to Application.Wait succeeds, in the other it fails - notice the debug output which returns either true or false)
    • the number of calls to the routine (one or two calls)

    I have no explanation for either of these differences, though.

    0 讨论(0)
  • 2020-12-29 15:39

    It would appear to me that what differs in the different ways of executing the code would be the thread that it runs on - the UI thread or a background thread, and the parser. Evaluate executed functions would be handled differently to explicitly defined functions, and functions called from the Immediate window would be handled slightly differently also.

    In:

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

    Evaluate ("SleepESub()") and [SleepESub()] appear to be expecting a formula, and Private Sub SleepESub() is not being executed at all.

    Depending on how the parser handles the procedure, each command may be executed in sequence in a single thread, resulting in the delay from the Application.Wait, or the Application.Wait may be considered to be valid only on the UI thread, and skipped when run on a background thread.

    This can be confirmed by the following code, executed by ?[SleepESub()] or ?Evaluate("SleepESub()") in the Immediate window:

    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
    

    When using the sapiSleep 5000 API call, the wait occurs (twice! - that bug that was mentioned), but when using Application.Wait Now + TimeValue("0:00:05"), no delay occurs.

    0 讨论(0)
提交回复
热议问题