[英]VBA dictionary <out of context> after Sub is run
I am trying to run the following code to create a dictionary that will then be used in a function to assign the functions parameter values depending on the dictionary key. 我正在尝试运行以下代码来创建字典,然后将其用于函数中,以根据字典键分配函数参数值。
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
Although this worked initially, after I temporarily changed the Sub to Static Sub it stopped working. 尽管此方法起初很有效,但在我将Sub临时更改为Static Sub之后,它停止了工作。 Changing it back to what it was in its last working condition has not fixed the problem.
将其改回其最后的工作状态仍无法解决问题。 Restarting VBA and running the code as a new module also haven't worked.
重新启动VBA并将代码作为新模块运行也没有用。
While debugging I can see in the Watch window that the dictionary b1 is created as it should, however after the Sub finishes it takes the value "out of context". 调试时,我可以在“监视”窗口中看到按需创建的字典b1,但是在Sub完成后,它将取值为“上下文无关”。 It doesn't make any sense, and it's now driving me crazy!
这没有任何意义,现在让我发疯! Can anyone help?
有人可以帮忙吗?
A couple of points: 要点:
Add a reference to the Microsoft Scripting Runtime library; 添加对Microsoft脚本运行时库的引用; this will allow you to use the actual types, instead of plain Object:
这将允许您使用实际类型,而不是普通对象:
Public b1 As Scripting.Dictionary
You could initialize the dictionary using the New
syntax: 您可以使用
New
语法初始化字典:
Public b1 As New Scripting.Dictionary
although this will only create the dictionary; 尽管这只会创建字典; it won't fill it;
它不会填满它; which brings us the the next point.
这给我们带来了下一点。
AFAIK, in VBA there is no constructor method for modules. AFAIK,在VBA中没有模块的构造方法。 So you'll have to verify that the dictionary has been filled, and perhaps test for initialization as well, before you try to use it:
因此,在尝试使用字典之前,您必须验证字典是否已填充,并可能还要测试初始化:
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
The Static
keyword won't make a difference here. Static
关键字在这里不会有所作为。 According to the documentation , the Static
keyword on a Function
or Sub
: 根据文档 ,在
Function
或Sub
上使用Static
关键字:
indicates that the
Sub
procedure's local variables are preserved between calls.指示在调用之间保留
Sub
过程的局部变量。 TheStatic
attribute doesn't affect variables that are declared outside theSub
, even if they are used in the procedure.即使在过程中使用了
Static
属性,Static
属性也不会影响在Sub
外部声明的变量。
and in this case the b1
variable has been declared outside of the Sub
. 在这种情况下,
b1
变量已在Sub
外部声明。
Using the Static
statement to declare module-level variables (such as b1
) will also have no effect -- in either case the value will last until the code is reset. 使用
Static
语句声明模块级变量(例如b1
)也不会起作用-在这两种情况下,值都将持续到重置代码为止。 It only makes a difference when declaring variables within a procedure. 它仅在过程中声明变量时有所不同。
Regarding the Watch window and the variables <out of context>
, when you add a Watch in the VBA IDE, you need to specify the context as <all procedures>
and <all modules>
. 关于“监视”窗口和变量
<out of context>
,在VBA IDE中添加Watch时,需要将上下文指定为<all procedures>
和<all modules>
。 Otherwise, the Watch variable will only be evaluated when the debugger is stopped within the selected module, and within the selected procedure. 否则,仅当调试器在所选模块内和所选过程内停止时,才会评估Watch变量。
Create a Static
Dictionary
inside the function. 在函数内部创建一个
Static
Dictionary
。 The dictionary will be populated the first time you use the function but after that the values will be retained and the relevant code skipped. 首次使用该函数时,将填充该词典,但此后将保留值,并跳过相关代码。
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
As others have pointed out, it's usually better to early-bind your variables. 正如其他人指出的那样,通常最好尽早绑定变量。 Which means if you know you want a
Dictionary
object, avoid declaring a Object
first and then converting it to a Dictionary
when you can just declare it as a Dictionary
right away. 这意味着如果你知道你想要一个
Dictionary
对象,避免声明一个Object
,然后再将其转换为一个Dictionary
时,你可以声明为一个Dictionary
的时候了。 To do this you need to include the reference to the Scripting Runtime Library and use: 为此,您需要包括对脚本运行时库的引用,并使用:
Dim b1 As Scripting.Dictionary
Set b1 = New Scripting.Dictionary
Do not use the single As New
statement below because it can cause unwanted errors (more here) 不要使用下面的单个
As New
语句,因为它可能导致不必要的错误(更多信息请参见此处)
Dim b1 As New Scripting.Dictionary
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.