如何在VBA中设置全局变量

4

我想在一个VBA模块中定义一个全局变量,并在其他VBA模块中使用它。

我正在尝试遵循以下步骤:如何在VBA中声明全局变量?

我创建了一个名为“GlobalVariables”的新模块,首先声明了公共变量,然后在函数内设置它们的值(尝试在公开代码中执行此操作会导致错误)。我的代码如下。

但是, Global 变量StartYear似乎无法在其他VBA模块中使用。我做错了什么?

Option Explicit

Public StartYear As Integer
Public BaseYear As Integer

Function DeclareGlobalVariables()
    StartYear = ActiveWorkbook.Worksheets("RunModel").Range("StartYear").Value
    BaseYear = ActiveWorkbook.Worksheets("RunModel").Range("BaseYear").Value
End Function

代码在我看来是正确的。你真的是说你不能在其他模块中使用这个变量,还是它只是没有你期望的值? - KekuSemau
你的代码看起来正确。我尝试了一下,可以在其他模块中访问变量。请检查它们是否被正确赋值。 - Mikku
1
DeclareGlobalVariables 应该是一个子程序而不是函数,你还需要执行它,以初始化全局变量。 - h2so4
1
与您的问题无关,但请勿使用“Integer”变量。该数据类型可能无法容纳您正在使用的数字值,从而导致溢出错误。 - JvdV
1个回答

5
  1. 请确保将全局变量放在模块中而不是工作表范围,以便在其他模块中可以访问它。

  2. 由于您的Function没有返回任何内容,因此应该将其改为Sub

  3. 如果您的单元格包含文本(字符串)等内容,则您的代码将出错。永远不要相信用户的输入。始终进行验证!

所以我建议如下:

模块1

Option Explicit

Public StartYear As Long
Public BaseYear As Long

Public Function InitializeGlobalVariables() As Boolean
    InitializeGlobalVariables = True
    With ActiveWorkbook.Worksheets("RunModel").Range("StartYear")
        If IsYear(.Value) Then
            StartYear = CLng(.Value)
        Else
            InitializeGlobalVariables = False
            MsgBox "StartYear needs to be a number"
        End If
    End With

    With ActiveWorkbook.Worksheets("RunModel").Range("BaseYear")
        If IsYear(.Value) Then
            BaseYear = CLng(.Value)
        Else
            InitializeGlobalVariables = False
            MsgBox "BaseYear needs to be a number"
        End If
    End With
End Function

'validate if the input value is a valid year
Private Function IsYear(ByVal InputValue As Variant) As Boolean
    If IsNumeric(InputValue) Then
        If CLng(InputValue) = InputValue And _
           InputValue > 0 And InputValue < 9999 Then 'integer not decimal AND 4 digit year
            IsYear = True
        End If
    End If
End Function

你可以在任何其他模块中访问变量,例如:

模块 2

Option Explicit

Public Sub TestOutput()
    'before using the variables test if they are initialized (not 0)
    If StartYear = 0 Or BaseYear = 0 Then 
        'they are not initalized so initalize them (and at the same time check if it was successful)
        If InitializeGlobalVariables = False Then 
            'the function returns FALSE if the initialization process failed so we need to cancel this procedure or we use not initilized variables!
             MsgBox "Variables were not intitialized. Trying to initialize them failed too. I cannot proceed."
             Exit Sub
        End If
    End If

    Debug.Print StartYear
    Debug.Print BaseYear
End Sub

谢谢PEH,感激不尽。从测试来看,似乎必须运行或调用子程序以初始化它。与我习惯的其他语言相比,这似乎有点笨拙。如果我有一堆将使用StartYear和BaseYear的函数,并且我不想将这些值作为参数不断传递,那么最好的初始化变量的方法是什么?在每个函数中调用DeclareGlobalVariables()似乎效率低下。最好在打开EXCEL工作簿时尝试调用此子程序吗? - brb
每个使用全局变量的函数/过程都需要检查它们是否已设置。如果在打开工作簿时初始化它们,则它们将被初始化直到关闭工作簿,但是如果任何地方出现问题并且代码意外停止,则全局变量可能未初始化(为0)。因此,您应该在每个过程/函数中检查变量是否已初始化(例如,检查它是否不为0,因为如果您依赖于它已初始化或是有效的用户输入,那么您可能会失败。 - Pᴇʜ
@brb 我将上面的过程更改为函数,以显示我的意思。这将是一种安全的方式,不依赖于任何关于全局变量值或状态的假设。 - Pᴇʜ

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