2013-07-05 25 views
7

Hi và chào mừng đến Evaluate() bí ẩn
Đánh giá() trong VBA


Các nhà phát triển tham khảo MSDN Văn phòng (2013) Tài liệu nói:

Sử dụng dấu ngoặc vuông (ví dụ, "[A1: C5]") giống hệt với cách gọi phương pháp Đánh giá bằng đối số chuỗi.


Vì vậy, tôi đã chạy một mã rất đơn giản để xem làm thế nào chính xác phương pháp Microsoft's Documentation of the Evaluate() là.
Không có gì đáng ngạc nhiên khi tôi nhận được kết quả ổn định mặc dù kỳ lạ.
lưu ý:thực hiện mỗi 4 lệnh trong Immediate WindowCTRL +G. Xem sự khác biệt trong mỗi cuộc gọi. Lưu ý rằng lỗi được tích hợp sẵn trong đó hiển thị mỗi MsgBox hai lần. Chỉ cần giữ ý nghĩ đó và không bị lẫn lộn ...
Stick mã này trong một module

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

sau đó thực hiện những lệnh 4 (1 tại một thời điểm) trong Immediate Window

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

Các đầu tiên 2 thực thi mã ngay lập tức; có nghĩa là với tôi họ đã đánh giá mã. Số thứ ba (theo tài liệu) phải là Evaluating nhưng không hoạt động theo cách tương tự giống như trong phần của mô-đun. Cửa sổ ngay lập tức đang đưa ra một số Error 2023 tuy nhiên cùng một cuộc gọi từ bên trong mô-đun của một mô-đun thực thi nó như thể bạn đang gọi một phụ.Đó đợi số 20 seconds như thể nó là số bình thường là Call SleepESub().

Có ai có thể giải thích những gì tôi thiếu ở đây không? Có phải dòng số 3 không phải là cuộc gọi Evaluation thích hợp không? hay nó đánh giá cuộc gọi đến tự phụ (nếu có ý nghĩa)


Cập nhật:
Tôi nghĩ một số người đang hiểu nhầm những gì tôi đang đánh giá đây - đừng lo lắng nó là một chủ đề nâng cao và tôi không phải là một nhà văn sách và bạn không phải là độc giả tâm trí. (tha thứ cho tôi ...)
Để có ý tưởng tốt hơn, bạn có thể so sánh kết quả từ cửa sổ ngay lập tức so với phần thân của mô-đun.Hãy thử mã này:

' 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 
+0

thú vị. tôi cần phải loại bỏ '?' cho hai cái cuối cùng. 'Run (" SleepESub ")' và 'Run (" SleepESub() ")' là tương tự nhưng 'Đánh giá (" SleepESub ")' không hoạt động. Chuyện gì vậy ?! –

+0

Với Excel 2010 (_Evaluate_ doc giống như 2013), '? Đánh giá ("SleepESub") 'trả về' Lỗi 2029'; tương tự cho '? [SleepESub] '. Tôi sẽ kết luận rằng năm 2010 là "sạch" (phù hợp với tài liệu) –

+1

@ d-stroyer '? [SleepESub] '(* được gọi từ cửa sổ ngay lập tức *) trả lại một' Lỗi 2029', tuy nhiên Nếu bạn thực hiện cuộc gọi tương tự trong phần thân của mô-đun, nó sẽ hoạt động, mặc dù không đánh giá nó thực hiện như thể bạn đang gọi một phụ . Tôi bắt đầu tự hỏi nếu các dấu ngoặc vuông chỉ được bỏ qua trong trường hợp này là trình biên dịch * nghĩ * '[SleepESub] = SleepyESub'. Mặt khác, nếu Cửa sổ ngay lập tức đưa ra một lỗi thì cuộc gọi giống nhau từ một mô-đun cơ thể hoạt động như thế nào? –

Trả lời

5

Nó sẽ xuất hiện với tôi rằng những gì khác nhau trong các cách khác nhau để thực thi mã sẽ là luồng mà nó chạy trên - chuỗi giao diện người dùng hoặc chuỗi nền và trình phân tích cú pháp. Evaluate các hàm được thực hiện sẽ được xử lý khác với các hàm được xác định rõ ràng và các hàm được gọi từ cửa sổ ngay lập tức cũng sẽ được xử lý hơi khác một chút.

Trong:

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

Evaluate ("SleepESub()")[SleepESub()] dường như đang chờ đợi một công thức, và Private Sub SleepESub() không được thực hiện ở tất cả.

Tùy thuộc vào cách trình phân tích cú pháp xử lý thủ tục, mỗi lệnh có thể được thực thi theo thứ tự trong một chuỗi đơn lẻ, dẫn đến độ trễ từ Application.Wait hoặc Application.Wait có thể được coi là hợp lệ chỉ trên chuỗi giao diện người dùng và bị bỏ qua khi chạy trên một chuỗi nền.

này có thể được xác nhận bởi các mã sau đây, được thực hiện bởi ?[SleepESub()] hoặc ?Evaluate("SleepESub()") trong cửa sổ Immediate:

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 

Khi sử dụng các cuộc gọi sapiSleep 5000 API, sự chờ đợi xảy ra (! Hai lần - đó là lỗi đã được đề cập) , nhưng khi sử dụng Application.Wait Now + TimeValue("0:00:05"), không xảy ra sự chậm trễ.

+0

Bạn đã đúng! Tôi đã sai khi giả định hai cuộc gọi đầu tiên đã được đánh giá, họ đã không - họ đã được thực thi một phần. 'Application.Wait' bị bỏ qua mặc dù msgbox được hiển thị nhưng nó không thực hiện' SleepESub' đúng cách. Nó tạo sự khác biệt gọi là 'ModuleBody' từ Module so với cửa sổ ngay lập tức. Điều đáng nói đến là '[SleepESub] = SleepESub'. –

+1

Trên thực tế, trong Đánh giá ("SleepESub()") và [SleepESub()], Private Sub SleepESub() không được thực thi - hãy thử thiết lập các điểm ngắt trên cả hai dòng Sub ModuleBody() và Private Sub SleepESub(), và bạn sẽ thấy khi bạn một bước thông qua mã mà Private Sub SleepESub() không được nhấn vào hai dòng này trong ModuleBody(). –

-1

Tôi nghĩ rằng đó là sai lầm khi tuyên bố rằng cuộc gọi thứ 3 không được đánh giá: nó không thực sự đánh giá đối tượng cung cấp, và trở về giá trị của nó (như tài liệu).

Tôi đã chút thay đổi các tiểu để minh họa:

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

Mỗi phòng trong số 4 cuộc gọi đánh giá thực sự sẽ trở lại 42 như mong đợi.

gì là khác nhau là:

  • bối cảnh ứng dụng (trong một trường hợp cuộc gọi đến Application.Wait thành công, trong kia nó không thành công - nhận thấy kết xuất debug mà lợi nhuận đúng hoặc sai)
  • số cuộc gọi đến thường lệ (một hoặc hai cuộc gọi)

Tôi không có lời giải thích nào về một trong những khác biệt này.