[英]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
關鍵字在這里不會有所作為。 根據文檔 ,在Function
或Sub
上使用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.