我正在尝试运行以下代码来创建一个字典,然后在函数中使用该字典根据字典键分配函数参数值。
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更改为静态Sub后,它停止了工作。将其更改回最后的工作状态并没有解决问题。重新启动VBA并将代码作为新模块运行也无法正常工作。
调试时我可以在Watch窗口中看到字典b1是按原样创建的,但是在Sub完成之后,它会取值“out of context”。它没有任何意义,它现在让我发疯!有人可以帮忙吗?
答案 0 :(得分:0)
有几点:
添加对 Microsoft Scripting Runtime 库的引用;这将允许您使用实际类型,而不是普通对象:
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
关键字在这里不会产生任何影响。根据{{3}},Static
或Function
上的Sub
关键字:
表示在调用之间保留
Sub
过程的局部变量。Static
属性不会影响在Sub
之外声明的变量,即使它们已在过程中使用。
在这种情况下,b1
变量已在Sub
之外声明。
使用Static
语句声明模块级变量(例如b1
)也不起作用 - 在任何一种情况下,该值都将持续到代码重置为止。它只在程序中声明变量时才有所不同。
关于Watch窗口和变量<out of context>
,在VBA IDE中添加Watch时,需要将上下文指定为<all procedures>
和<all modules>
。否则,仅当调试器在所选模块中停止并且在所选过程中停止时,才会评估Watch变量。
答案 1 :(得分:0)
在函数内创建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
声明,因为它可能会导致意外错误(more here)
Dim b1 As New Scripting.Dictionary