簡體   English   中英

VBA字典 <out of context> 在Sub運行之后

[英]VBA dictionary <out of context> after Sub is run

我正在嘗試運行以下代碼來創建字典,然后將其用於函數中,以根據字典鍵分配函數參數值。

Option Explicit

Public b1 As Object
Public var1 As Variant
Public var2 As String
Public var3 As Variant

Sub CreateDictionaries()
    Set b1 = CreateObject("Scripting.Dictionary")
    b1.Add "key1", 0.009
    b1.Add "key2", 0.011
    b1.Add "key3", 0.014
    b1.Add "key4", 0.025
    b1.Add "key5", 0.045
End Sub

Public Function MyFunction(var1, var2, var3)
    If var1 <= 5 Then
        MyFunction = b1.Item(var2) * var1* var3
    ElseIf var1 > 5 And var1 <= 10 Then
        MyFunction = b1.Item(var2) * (var1 - 5) * var3
    ElseIf var1 > 10 Then
        MyFunction  = b1.Item(var2) * (var1 - 10) * var3    
    End If
End Function

盡管此方法起初很有效,但在我將Sub臨時更改為Static Sub之后,它停止了工作。 將其改回其最后的工作狀態仍無法解決問題。 重新啟動VBA並將代碼作為新模塊運行也沒有用。

調試時,我可以在“監視”窗口中看到按需創建的字典b1,但是在Sub完成后,它將取值為“上下文無關”。 這沒有任何意義,現在讓我發瘋! 有人可以幫忙嗎?

要點:

  • 添加對Microsoft腳本運行時庫的引用; 這將允許您使用實際類型,而不是普通對象:

     Public b1 As Scripting.Dictionary 
  • 可以使用New語法初始化字典:

     Public b1 As New Scripting.Dictionary 

    盡管這只會創建字典; 它不會填滿它; 這給我們帶來了下一點。

  • AFAIK,在VBA中沒有模塊的構造方法。 因此,在嘗試使用字典之前,您必須驗證字典是否已填充,並可能還要測試初始化​​:

     Public b1 As Scripting.Dictionary Sub InitializeDictionary() If Not b1 Is Nothing Then Exit Sub Set b1 = New Scripting.Dictionary b1.Add "key1", 0.009 b1.Add "key2", 0.011 b1.Add "key3", 0.014 b1.Add "key4", 0.025 b1.Add "key5", 0.045 End Sub Public Function MyFunction(var1, var2, var3) InitializeDictionary If var1 <= 5 Then MyFunction = b1.Item(var2) * var1* var3 ElseIf var1 > 5 And var1 <= 10 Then MyFunction = b1.Item(var2) * (var1 - 5) * var3 ElseIf var1 > 10 Then MyFunction = b1.Item(var2) * (var1 - 10) * var3 End If End Function 
  • Static關鍵字在這里不會有所作為。 根據文檔 ,在FunctionSub上使用Static關鍵字:

    指示在調用之間保留Sub過程的局部變量。 即使在過程中使用了Static屬性, Static屬性也不會影響在Sub外部聲明的變量。

    在這種情況下, b1變量已在Sub外部聲明。

    使用Static語句聲明模塊級變量(例如b1 )也不會起作用-在這兩種情況下,值都將持續到重置代碼為止。 它僅在過程中聲明變量時有所不同。

  • 關於“監視”窗口和變量<out of context> ,在VBA IDE中添加Watch時,需要將上下文指定為<all procedures><all modules> 否則,僅當調試器在所選模塊內和所選過程內停止時,才會評估Watch變量。

在函數內部創建一個Static Dictionary 首次使用該函數時,將填充該詞典,但此后將保留值,並跳過相關代碼。

Option Explicit

Public Function MyFunction(var1, var2, var3)

    Static b1 As Object   
    If b1 Is Nothing Then
        Set b1 = CreateObject("Scripting.Dictionary")
        b1.Add "key1", 0.009
        b1.Add "key2", 0.011
        b1.Add "key3", 0.014
        b1.Add "key4", 0.025
        b1.Add "key5", 0.045
    End If

   If var1 <= 5 Then
        MyFunction = b1.Item(var2) * var1* var3
    ElseIf var1 > 5 And var1 <= 10 Then
        MyFunction = b1.Item(var2) * (var1 - 5) * var3
    ElseIf var1 > 10 Then
        MyFunction  = b1.Item(var2) * (var1 - 10) * var3    
    End If
End Function

正如其他人指出的那樣,通常最好盡早綁定變量。 這意味着如果你知道你想要一個Dictionary對象,避免聲明一個Object ,然后再將其轉換為一個Dictionary時,你可以聲明為一個Dictionary的時候了。 為此,您需要包括對腳本運行時庫的引用,並使用:

Dim b1 As Scripting.Dictionary
Set b1 = New Scripting.Dictionary

不要使用下面的單個As New語句,因為它可能導致不必要的錯誤(更多信息請參見此處)

Dim b1 As New Scripting.Dictionary

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM