如何在 VBA 中声明一个全局变量?

Posted

技术标签:

【中文标题】如何在 VBA 中声明一个全局变量?【英文标题】:How do I declare a global variable in VBA? 【发布时间】:2011-02-12 21:49:12 【问题描述】:

我写了以下代码:

Function find_results_idle()

    Public iRaw As Integer
    Public iColumn As Integer
    iRaw = 1
    iColumn = 1

我收到错误消息:

“子或函数中的无效属性”

你知道我做错了什么吗?

我尝试使用Global 而不是Public,但遇到了同样的问题。

我尝试将函数本身声明为 `Public,但这也没有用。

创建全局变量需要做什么?

【问题讨论】:

【参考方案1】:

我发现最好的方法是为工作簿分配一个属性

只要工作簿打开,它的范围就一直有效

Public WhenOpened As Date

Private Sub Workbook_Open()
   ThisWorkbook.WhenOpened = Now()
End Sub

【讨论】:

【参考方案2】:

你也可以使用 -

Private Const SrlNumber As Integer = 910

Private Sub Workbook_Open()
    If SrlNumber > 900 Then
        MsgBox "This serial number is valid"
    Else
        MsgBox "This serial number is not valid"
    End If
End Sub

已在 office 2010 上测试

【讨论】:

【参考方案3】:

创建公共/全局变量的一个好方法是将表单视为类对象并声明属性并使用 Public Property Get [variable] 来访问属性/方法。此外,您可能需要引用或将引用传递给实例化的 Form 模块。如果您对已关闭的表单/报告调用方法,您将收到错误。 示例:将 Me.Form.Module.Parent 传递给子/函数而不是表单内部。

Option Compare Database 
Option Explicit
''***********************************''
' Name: Date: Created Date Author: Name 
' Current Version: 1.0
' Called by: 
''***********************************''
' Notes: Explain Who what when why... 
' This code Example requires properties to be filled in 
''***********************************''
' Global Variables
Public GlobalData As Variant
''***********************************''
' Private Variables
Private ObjectReference As Object
Private ExampleVariable As Variant
Private ExampleData As Variant
''***********************************''
' Public properties
Public Property Get ObjectVariable() As Object
   Set ObjectVariable = ObjectReference
End Property 
Public Property Get Variable1() As Variant 
  'Recommend using variants to avoid data errors
  Variable1 = ExampleVariable
End property
''***********************************''
' Public Functions that return values
Public Function DataReturn (Input As Variant) As Variant
   DataReturn = ExampleData + Input
End Function 
''***********************************''
' Public Sub Routines
Public Sub GlobalMethod() 
   'call local Functions/Subs outside of form
   Me.Form.Refresh
End Sub
''***********************************''
' Private Functions/Subs used not visible outside 
''***********************************''
End Code

所以在另一个模块中你可以访问:

Public Sub Method1(objForm as Object)
   'read/write data value
   objForm.GlobalData
   'Get object reference (need to add Public Property Set to change reference object)
   objForm.ObjectVariable
   'read only (needs Public property Let to change value)
   objForm.Variable1
   'Gets result of function with input
   objForm.DataReturn([Input])
   'runs sub/function from outside of normal scope
   objForm.GlobalMethod
End Sub

如果您像我一样使用后期绑定,那么在尝试进行任何处理之前,总是会检查 Null 值和空对象。

【讨论】:

【参考方案4】:

正如其他人所说,问题实际上是关于范围的。

简而言之,考虑这个“模块”:

Public Var1 As variant     'Var1 can be used in all
                           'modules, class modules and userforms of 
                           'thisworkbook and will preserve any values
                           'assigned to it until either the workbook
                           'is closed or the project is reset.

Dim Var2 As Variant        'Var2 and Var3 can be used anywhere on the
Private Var3 As Variant    ''current module and will preserve any values
                           ''they're assigned until either the workbook
                           ''is closed or the project is reset.

Sub MySub()                'Var4 can only be used within the procedure MySub
    Dim Var4 as Variant    ''and will only store values until the procedure 
End Sub                    ''ends.

Sub MyOtherSub()           'You can even declare another Var4 within a
    Dim Var4 as Variant    ''different procedure without generating an
End Sub                    ''error (only possible confusion). 

您可以查看此MSDN reference 以了解有关变量声明的更多信息,以及查看其他Stack Overflow Question 了解有关变量如何超出范围的更多信息。

另外两件事:

    使用工作簿级别变量时要井井有条,这样您的代码就不会混乱。首选函数(具有适当的数据类型)或传递参数ByRef。 如果您希望变量在调用之间保持其值,您可以使用 Static 语句。

【讨论】:

您确定全局变量可以在不同的工作簿中使用吗?不适合我 好点!我注意到我没有添加关于我从哪里获得该信息的参考......我也没有再次找到它。最好编辑答案...:/哦,谢谢 Seb。【参考方案5】:

在通用声明中创建一个公共整数。

然后在你的函数中你可以每次都增加它的值。 查看示例(将电子邮件的附件保存为 CSV 的功能)。

Public Numerator As Integer

Public Sub saveAttachtoDisk(itm As Outlook.MailItem)
Dim objAtt As Outlook.Attachment
Dim saveFolder As String
Dim FileName As String

saveFolder = "c:\temp\"

     For Each objAtt In itm.Attachments
            FileName = objAtt.DisplayName & "_" & Numerator & "_" & Format(Now, "yyyy-mm-dd H-mm-ss") & ".CSV"
                      objAtt.SaveAsFile saveFolder & "\" & FileName
                      Numerator = Numerator + 1

          Set objAtt = Nothing
     Next
End Sub

【讨论】:

【参考方案6】:

这是一个关于scope的问题。

如果您只希望变量持续函数的生命周期,请在函数或子函数中使用DimDimension 的缩写)来声明变量:

Function AddSomeNumbers() As Integer
    Dim intA As Integer
    Dim intB As Integer
    intA = 2
    intB = 3
    AddSomeNumbers = intA + intB
End Function
'intA and intB are no longer available since the function ended

global 变量(正如 SLaks 指出的那样)在函数外部使用 Public 关键字声明。此变量将在您运行的应用程序的生命周期内可用。对于 Excel,这意味着只要该特定 Excel 工作簿处于打开状态,变量就可用。

Public intA As Integer
Private intB As Integer

Function AddSomeNumbers() As Integer
    intA = 2
    intB = 3
    AddSomeNumbers = intA + intB
End Function
'intA and intB are still both available.  However, because intA is public,  '
'it can also be referenced from code in other modules. Because intB is private,'
'it will be hidden from other modules.

您还可以使用Private 关键字声明只能在特定模块(或类)中访问的变量。

如果您正在构建一个大型应用程序并且需要使用全局变量,我建议您为您的全局变量创建一个单独的模块。这应该可以帮助您在一个地方跟踪它们。

【讨论】:

+1 7 年后仍然有用。但是关于对象变量与数据变量是否有一些额外的细微差别?我遇到了一个与范围对象变量相关的问题,它提示了一个新问题。非常感谢您有时间看一看。 ***.com/q/46058096/5457466 我尝试了所有其他关于“范围”的建议,但没有一个奏效。唯一有效的是一个专门用于全局变量的新模块,它有效!【参考方案7】:

如果这个函数在一个模块/类中,你可以把它们写在函数之外,所以它有Global Scope。全局作用域意味着变量可以被同一个模块/类中的另一个函数访问(如果你使用dim作为声明语句,如果你希望变量可以被所有函数访问,使用public在所有模块中):

Dim iRaw As Integer
Dim iColumn As Integer

Function find_results_idle()
    iRaw = 1
    iColumn = 1
End Function

Function this_can_access_global()
    iRaw = 2
    iColumn = 2
End Function

【讨论】:

【参考方案8】:

要使用全局变量,请从 VBA 项目 UI 中插入新模块并使用 Global 声明变量

Global iRaw As Integer
Global iColumn As Integer

【讨论】:

PublicGlobal关键字声明有什么区别? "Public and Global are nearly identical in their function .. Global comes from older versions of VB"【参考方案9】:

需要在函数外声明变量:

Public iRaw As Integer
Public iColumn As Integer

Function find_results_idle()
    iRaw = 1
    iColumn = 1

【讨论】:

当我尝试将数组声明为公共时,它会说:数组和用户定义的数据类型不能声明为公共。 以上第一个Function/Sub,不只是在外面:"模块级变量可以在顶部用 Dim 或 Private 语句声明第一个过程定义上面的模块。”(来自Scope of variables in Visual Basic for Applications)

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

如何在 VBA 中设置全局变量

如何从 Access VBA 中的另一个私有子获取私有子中声明的变量的值

Excel vba:打开工作簿时分配全局变量;如果发生错误则被删除

如何在打字稿中声明全局变量

什么是全局变量

如何(如果可能)从 VBA Excel 2010 的工作表中定义和填充全局数组变量?