8

Evaluate()の謎へようこそ


MSDN Office Developer Reference (2013) Documentation には次のように書かれています。

角かっこ ("[A1:C5]" など) を使用することは、文字列引数を指定して Evaluate メソッドを呼び出すことと同じです。


そこで、非常に単純なコードを実行して、Microsoft の Evaluate()メソッドのドキュメントがどれほど正確かを確認しました。
驚くべきことではありませんが、一貫した結果ではありますが、奇妙な結果が得られます。
注: +内の 4 つのコマンドをそれぞれ実行します。それぞれの呼び出しの違いを見てくださいImmediate Window CTRLG各 MsgBox が 2 回表示される組み込みのバグに注意してください。それを覚えておいて、混乱しないでください... このコードをモジュールに貼り付けます

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

次に、これらの 4 つのコマンド (一度に 1 つ) をイミディエイト ウィンドウで実行します。

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

最初の 2 つはコードをすぐに実行します。私にとっては、彼らがコードを評価したことを意味します。3番目のもの(ドキュメントによると)はそうあるべきですが、モジュールの本体とEvaluating同じようには機能しません。イミディエイト ウィンドウは、モジュールの本体内からの同じ呼び出しを行っていますが、サブを呼び出しているかのように実行されます。4 番目の呼び出しである通常の場合と同様に待機します。 ここで私が見逃していることを誰かが説明できますか? 回線番号 3 は適切な呼び出しではありませんか? または、サブ自体への呼び出しを評価しますか(それが理にかなっている場合)Error 202320 secondsCall SleepESub()

Evaluation


更新:
一部の人々は、私がここで評価していることを誤解していると思います。これは高度なトピックであることを心配しないでください。(許してください... )
より良いアイデアを得るために、即時ウィンドウとモジュール本体の結果を比較できます。このコードを試してください:

' 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
4

2 に答える 2

6

コードを実行するさまざまな方法で異なるのは、コードが実行されるスレッド (UI スレッドまたはバックグラウンド スレッド) とパーサーであるように私には思えます。 Evaluate実行された関数は、明示的に定義された関数とは異なる方法で処理され、イミディエイト ウィンドウから呼び出された関数もわずかに異なる方法で処理されます。

の:

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

Evaluate ("SleepESub()")[SleepESub()]数式を期待しているように見え、まったく Private Sub SleepESub()実行されていません。

パーサーがプロシージャを処理する方法に応じて、各コマンドが 1 つのスレッドで順番に実行され、 からの遅延が発生する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

API呼び出しを使用するsapiSleep 5000と、待機が発生します(2回!-言及されたバグ)が、を使用するApplication.Wait Now + TimeValue("0:00:05")と遅延は発生しません。

于 2013-07-23T00:18:15.103 に答える
-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 を返すデバッグ出力に注意してください)
  • ルーチンへの呼び出しの数 (1 回または 2 回の呼び出し)

ただし、これらの違いのいずれについても説明はありません。

于 2013-07-09T08:27:17.393 に答える