在Excel VBA中的公共静态变量

18

在使用Excel VBA时,是否可以在一个过程中声明一个静态变量,并在多个不同的过程中使用该变量?

即:

Public myvar as integer

Sub SetVar()
   static myvar as integer
   myvar=999
end sub

sub Usevar()
    dim newvar as integer
    newvar=myvar*0.5
end sub

我需要其他过程能看到myvar,并且不会改变或丢失。如果myvar没有声明为静态变量,则上面的代码有效,但是在更多代码后变量就“丢失”了。如果使用静态声明,usevar过程将无法看到myvar。而“Public Static myvar as integer”在VBA中不被接受。

谢谢你的帮助

Zeus


2
全局变量始终是静态的,因为它保持其值,除非代码执行被停止。如果这就是你想要一个静态变量的原因,那么使用一个全局变量。 - Tim Williams
Tim,感谢你编辑我的帖子并回答我的问题。我只想在一个模块中的几个过程中初始化几个集合,然后在另一个模块的几个过程中使用这些集合。将它们声明为Public确实有所帮助,但是现在我遇到了运行时错误91:对象变量或With块变量未设置,而且我不知道原因。代码似乎在执行过程中正常运行,直到代码停止执行或代码被更改。有没有办法使其更加健壮,比如使用Set语句? - Zeus
我通过在每次运行时在使用它们的过程中初始化集合来解决了这个问题,但这似乎是一个不好的解决方案。 - Zeus
如果您不喜欢自己的解决方案,为什么不将其作为更新发布并寻求建议呢? - Tim Williams
2
Public Const myvar as integer = 999 - Patrick Lepelletier
3个回答

10

通过调用MAIN()来尝试此操作:

Public myvar As Integer

Sub MAIN()
    Call SetVar
    Call UseVar
End Sub

Sub SetVar()
    myvar = 999
End Sub

Sub UseVar()
    Dim newvar As Variant
    newvar = myvar * 0.5
    MsgBox newvar
End Sub

如果你将一个项目声明为 静态(Static),它的值将在过程或子程序中保持不变。
如果你将该项目声明为 公共(Public),它的值将被保留并且其他程序也可以访问。


1
谢谢Gary的学生。您的解决方案可行,但是如果我更改代码,会出现运行时91错误,指出对象变量或块变量未设置。我不确定它的含义。我需要在usevar()中设置集合吗?setvar和usevar也在不同的模块中。 - Zeus
通过更改代码,我指的是更改程序的行位置 - 仅将其移动到“声明”之前。 - Zeus
有没有比在每个过程中初始化集合更有效的方法? - Zeus
在模块的顶部声明变量时,使用“Dim”关键字可以使其在该模块中的所有子程序和函数中可用。将其声明为“Public”则可以使其在其他模块中也可用......我不确定事件代码是否也能“看到”它。 - Gary's Student
谢谢,问题似乎出现在代码更改(仍在开发中)或出现错误并且所有变量都被重置时。那么,在usevar过程中可能需要进行某种类型的错误检查?如果集合为空,则刷新? - Zeus
@Zeus - 错误是由于在VBA中发生的大约16种不同编译状态之间转换会清除整个“项目”中的所有变量。我通过调用“包装器”属性来解决这个问题,以检查初始化状态。 - Roger Willcocks

8
尽管这个问题已经由@Gary's Student在四年前回答过了,但是有一个微妙的细节值得一提,因为解决方案可能取决于myvar的数据类型。

首先,正如你在问题中所指出的那样,Public Static myvar as Integer是不起作用的,因为Static只允许在子程序或函数内部使用。

如@Patrick Lepelletier在OP的评论中所述,您可以通过声明一个Constant来轻松解决此问题(假设您不需要动态更改它):Public Const myvar as Integer = 999。(或者可能是Private Const myvar...

另一个选择是将myvar声明为一个函数而不是变量或常量,从而有效地将其转换为一个伪常量

Private Function myvar() as Integer
     Static intMyvar as Integer 
     intMyvar = 999
     myvar = intMyvar
End function

在这个简单的示例中,myvar 是一个整数,伪常量方法显然是不必要的,并增加了函数调用的开销。只需声明一个 Constant 即可完成任务。但是,仅当值是静态的且不是对象时,才能使用常量。如果 myvar 是一个对象,例如 Range,则无法使用常量。在这种情况下,使用伪常量可能会很有用:
Private Function myvar() as Range
    Set myvar = Range("A1")
End Function

另一个优点是,您可以在函数内部使用代码来检查特定条件并相应地为myvar分配不同的值。

伪常量方法也可以与命名工作表范围相结合:如果单元格A1是一个命名范围,比如MyRange,那么您可以写:

Dim strMyString as String
strMyString = "MyRange"
Private Function myvar() as Range
    Set myvar = Range(strMyString)
End Function

现在可以在不破坏代码的情况下移动单元格A1的内容,因为如果您剪切和粘贴单元格,则命名范围会跟随移动。我发现这种方法在设计阶段很有用,因为工作表中的事物往往会频繁移动。

伪常量还有助于避免通常与全局变量(或模块级变量)相关的某些问题,这可能是大型项目中的一个问题。


1
关键在于使用两个变量。在下面的代码中,myvar是公共的但不是静态的。stvar是静态的但不是公共的。它的作用域仅限于Main()函数内部。通过将myvar=stvar和stvar=myvar赋值,有效地创建了一个既是公共的又是静态的变量。该值被保留。
Public myvar As String
Sub Main() 'in module 1
Static stvar As String
myvar = stvar
toInput
stvar = myvar
End Sub

Sub toInput() 'in module2
myvar = InputBox("enter something", "Input", myvar)
End Sub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接