在VBA中声明一个公共变量并赋予默认值是否可行?

71

我想这样做,但它不能编译:

Public MyVariable as Integer = 123

如何最好地实现这个目标?


这个 VBA 是在哪里运行的?Excel、Access、Word... - Duncan Howe
@DuncanHowe 我希望得到一个通用的VBA解决方案。 - David
4
全局变量现在不再被认为是邪恶的了吗?我五月份离开了几个星期,可能错过了一些东西。 - Jean-François Corbett
9个回答

122

.NET已经把我们宠坏了 :)

您的声明在VBA中是无效的。

只有常量可以在应用程序加载时赋值。您应该像这样声明它们:

Public Const APOSTROPHE_KEYCODE = 222

这是我一个VBA项目中的样例声明:

VBA常量图片

如果你想要声明一个公共变量并初始化它的值,你需要创建一个Workbook_Open子程序,并在其中进行初始化。示例:

Private Sub Workbook_Open()
  Dim iAnswer As Integer

  InitializeListSheetDataColumns_S
  HideAllMonths_S

  If sheetSetupInfo.Range("D6").Value = "Enter Facility Name" Then
    iAnswer = MsgBox("It appears you have not yet set up this workbook.  Would you like to do so now?", vbYesNo)
    If iAnswer = vbYes Then
      sheetSetupInfo.Activate
      sheetSetupInfo.Range("D6").Select
      Exit Sub
    End If
  End If

  Application.Calculation = xlCalculationAutomatic
  sheetGeneralInfo.Activate
  Load frmInfoSheet
  frmInfoSheet.Show


End Sub

确保在Workbook对象本身中声明子程序: 输入图像描述于此


Excel 返回一个错误,指出变量不允许作为对象模块的公共成员。 - Bobin

13

提供一个不同的角度 -

我认为在函数调用之间维护公共变量不是一个好主意。你需要使用的任何变量都应该存储在子程序和函数中,并作为参数传递。一旦代码运行完成,你就不应该期望VBA项目保持任何变量的值。

原因是,在使用工作簿时,有很多事情可能会无意中重置VBA项目。当发生这种情况时,任何公共变量都将被重置为0。

如果你需要存储在子程序和函数之外的值,我强烈建议使用一个隐藏的工作表和命名范围来存储需要持久化的任何信息。


我不同意这种思维方式。这就像是在不同的子程序中复制粘贴相同的代码块,而不是创建一个单独的子程序块或者使用一个模块来处理它。 - undefined

10

当然您知道,但如果它是一个常量,则应该使用 const MyVariable as Integer = 123。否则,您没有运气了;变量必须在其他地方分配初始值。

您可以:

public property get myIntegerThing() as integer
    myIntegerThing= 123
end property

在一个类模块中创建它,然后在全局范围内使用。

public cMyStuff as new MyStuffClass

所以cMyStuff.myIntegerThing立即可用。


1
更好的方法是添加一个模块并在此模块内定义这些属性。我创建了一个名为“Globals”的模块,并在其中定义了“Property Get”,它非常有效。
Property Get PSIStartRow() As Integer
PSIStartRow = Sheets("FOB Prices").Range("F1").Value
End Property
Property Get PSIStartCell() As String
PSIStartCell = "B" & PSIStartRow
End Property
- Achilles
以上评论中的代码被搞乱了。我会在下面发布它。 - Achilles

9

鲜为人知的事实:
命名范围可以引用一个值而不是特定单元格。

这可以被利用来像“全局变量”一样操作,并且您可以从VBA和工作表单元格中引用该值,而且分配的值甚至在关闭并重新打开工作簿后仍然存在


  • To "declare" the name myVariable and assign it a value of 123:

    ThisWorkbook.Names.Add "myVariable", 123
    
  • To retrieve the value (for example to display the value in a MsgBox):

      MsgBox [myVariable]
    
  • Alternatively, you could refer to the name with a string: (identical result as square brackets)

    MsgBox Evaluate("myVariable")
    
  • To use the value on a worksheet just use it's name in your formula as-is:

    =myVariable
    
  • In fact, you could even store function expressions: (sort of like in JavaScript)
    (Admittedly, I can't actually think of a situation where this would be beneficial - but I don't use them in JS either.)

    ThisWorkbook.Names.Add "myDay", "=if(isodd(day(today())),""on day"",""off day"")"
    

方括号只是Evaluate方法的快捷方式。我听说使用它们被认为是混乱或“hacky”,但是我没有遇到任何问题,而且它们在Excel中的使用得到了Microsoft的支持。
可能还有一种方法可以使用Range函数来引用这些名称,但我没有看到任何优势,所以我没有深入研究。

更多信息:


这太棒了,我用Excel工作多年,从未知道这个。我肯定会将来用到这个。通常我使用一个名为"设置"的工作表来存储这些信息。如果有很多不同的设置,那当然没问题。但如果只需要1或2个设置,那么为此使用整个工作表感觉浪费。 - Ale

4
如上所述,要声明全局可访问变量,您可以在函数外部使用public关键字进行声明。
由于赋值在程序外部是不被允许的,因此您可以创建一个名为InitGlobals的子程序来初始化公共变量,然后在语句开头调用此子程序。
以下是一个示例:
Public Coordinates(3) as Double
Public Heat as double
Public Weight as double

Sub InitGlobals()
    Coordinates(1)=10.5
    Coordinates(2)=22.54
    Coordinates(3)=-100.5
    Heat=25.5
    Weight=70
End Sub

Sub MyWorkSGoesHere()
    Call InitGlobals
    'Now you can do your work using your global variables initialized as you wanted them to be.
End Sub

2

您可以在“通用声明”中定义变量,然后在环境中触发的第一个事件中对其进行初始化。

或者,您可以创建一个包含相关属性并在“初始化”方法中对其进行初始化的类。


2
这是我在需要初始化全局常量时所做的:
1. 添加一个名为Globals的模块
2. 在Globals模块中添加以下属性:
Property Get PSIStartRow() As Integer  
    PSIStartRow = Sheets("FOB Prices").Range("F1").Value  
End Property  
Property Get PSIStartCell() As String  
    PSIStartCell = "B" & PSIStartRow  
End Property

0

有一种正确解决您问题的方法。我长期以来也有同样的疑虑。经过长时间的搜索和学习,我终于找到了这类问题的解决方案。

解决方案是不需要声明变量,也不需要给变量赋值,甚至不需要使用VBA代码。只需要在Excel中使用“命名区域”即可。

例如,“A1”单元格内容为“hello, world”。我们将“A1”单元格定义为名称“hello”,也就是说,“A1”单元格现在有一个名称,叫做“hello”。 在VBA代码中,我们只需要使用这个方法[hello],就可以获取“A1”的值。

Sub test()
msgbox [hello]
end sub

msgbox 会显示 "Hello, word"。

这样,我们可以获得一个全局变量,而不需要任何声明或赋值。它可以在任何子程序或函数中使用。

我们可以在 Excel 中定义许多命名区域,在 VBA 代码中只需使用 [] 方法即可获取区域值。

实际上,[hello] 是函数 Evaluate["Hell"] 的缩写,但更短。


-2

已经有一段时间了,但这可能会满足您:

Public MyVariable as Integer: MyVariable = 123

这有点丑,因为你必须重新输入变量名,但它只占一行。


5
它产生了编译错误:过程外无效。 - manpreet

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