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


132

我写了以下代码:

Function find_results_idle()

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

我收到错误消息:

“ Sub或Function中的无效属性”

你知道我做错了吗?

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

我试图将函数本身声明为`Public,但这也没有好处。

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

Answers:


177

您需要在函数外部声明变量:

Public iRaw As Integer
Public iColumn As Integer

Function find_results_idle()
    iRaw = 1
    iColumn = 1

当我尝试将数组声明为公共数组时,它说:数组和用户定义的数据类型不能声明为公共数组。
kapilddit

第一个Function/ 之上Sub,而不仅仅是在外部:“可以在第一个过程定义上方的模块顶部,使用Dim或Private语句声明模块级变量。” (来自Visual Basic for Applications中的变量范围
Nickolay

119

这是关于范围的问题。

如果只希望变量在函数的生存期内有效,请在函数或子函数内使用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

全局变量(如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关键字声明变量,还可以使变量只能在特定模块(或类)中访问。

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


4
+1在7年后仍然有用。但是在对象变量和数据变量之间是否还有其他细微差别?我遇到了与范围界定对象变量有关的问题,该问题提示了一个新问题。非常感谢您有时间来看看。stackoverflow.com/q/46058096/5457466
Egalth'9

2
VBA中变量声明的简要说明。
PhillipOReilly

我尝试了所有其他有关“范围”的建议,但都没有奏效。唯一起作用的是专门用于全局var的新模块,它起作用了!
Fandango68年


18

正如另一个人所说的,问题实际上是关于范围的。

简而言之,请考虑以下“模块”:

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参考,以获取有关变量声明的更多信息,以及有关另一个堆栈溢出问题,以获取有关变量如何超出范围的更多信息。

另外两件事:

  1. 使用工作簿级别的变量时要组织得井井有条,因此您的代码不会混乱。首选函数(具有适当的数据类型)或传递参数ByRef
  2. 如果希望变量在两次调用之间保留其值,则可以使用Static语句。

您确定全局变量可以在不同的工作簿中使用吗?我不工作
勒布

好点子!我注意到我没有为获得信息的地方添加参考...也没有找到它。最好编辑答案...:/哦,谢谢塞伯。
FCastro

14

如果此函数在模块/类中,则可以在函数外部编写它们,因此它具有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

1

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

然后,您可以在函数中每次增加其值。请参见示例(将电子邮件附件另存为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

0

创建Public / Global变量的一种好方法是将Form视为类对象,并声明属性,然后使用Public Property Get [variable]访问属性/方法。另外,您可能需要引用或将引用传递给实例化的Form模块。如果您对关闭的表单/报表调用方法,则会收到错误消息。
示例:将Me.Form.Module.Parent传递到sub / function而不是表单内部。

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

如果您像我一样使用Late Binding,那么在尝试执行任何处理之前,请务必检查Null值和Nothing对象。


0

您也可以使用-

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上经过测试

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.