如何在 VBA 中设置全局变量

Posted

技术标签:

【中文标题】如何在 VBA 中设置全局变量【英文标题】:How to set global variables in VBA 【发布时间】:2019-07-15 06:17:17 【问题描述】:

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

我正在尝试关注:How do I declare a global variable in 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

【问题讨论】:

代码对我来说似乎是正确的。你真的是说你不能在其他模块中使用这个变量,还是它没有你期望的值? 您的代码看起来正确。我试过了,我可以访问其他模块中的变量。检查它们是否被正确分配了值。 DeclareGlobalVariables 应该是 sub 而不是函数,你还需要执行它,才能初始化全局变量。 与您的问题无关,但不要使用Integer 变量。此数据类型可能无法保存您正在使用的数值,从而导致溢出错误。 【参考方案1】:

    确保将全局变量放在模块中而不是工作表范围内,以使其在其他模块中可访问。

    您的Function 应该是Sub,因为它不返回任何内容。

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

所以我建议如下

模块 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,不胜感激。从测试来看,您似乎必须运行或调用 sub 来初始化它。考虑到我习惯使用的其他语言,这似乎有点笨拙。如果我有一堆将使用 StartYear 和 BaseYear 的函数,并且我不想继续将这些值作为参数输入,那么初始化变量的最佳方法是什么?在每个函数中调用 DeclareGlobalVariables() 似乎效率低下。是否最好在打开 EXCEL 工作簿时尝试调用此子程序? 嗯,每个使用全局变量的函数/过程都需要检查它们是否被设置。如果您在打开工作簿时初始化它们,它们将被初始化,直到工作簿关闭,但如果出现任何问题并且代码意外停止,则全局变量可能最终未初始化(beeing 0)。因此,如果变量已初始化,您应该检查每个过程/函数(例如,检查它是否不是0,因为如果您依赖它进行初始化或获取有效的用户输入,那么您最终可能会导致过程失败. @brb 我把上面的过程改成了一个函数来表达我的意思。这是一种不依赖任何关于全局变量的值或状态的假设的安全方法。

以上是关于如何在 VBA 中设置全局变量的主要内容,如果未能解决你的问题,请参考以下文章

37如何在函数中设置一个全局变量 ?

如何在 asp.net c# 渲染覆盖中设置全局变量?

如何在另一个模块中设置全局变量?

在 Xcode 构建阶段运行脚本中设置全局环境变量

在R中的引用类中设置全局变量

Postman 中设置全局变量,token