如何在Excel VBA中声明全局变量,以便在整个工作簿中可见

21

我有一个关于全局作用域的问题,并将问题抽象成了一个简单的例子:

在Excel工作簿中:
Sheet1中我有两个按钮。
第一个按钮标记为SetMe,并链接到Sheet1模块中的一个子程序:
Sheet1代码:

Option Explicit
Sub setMe()
    Global1 = "Hello"
End Sub

第二个标签被标记为ShowMe,并且链接到 ThisWorkbook的模块中的一个子程序:
ThisWorkbook代码:

Option Explicit
Public Global1 As String
Debug.Print("Hello")
Sub showMe()
    Debug.Print (Global1)
End Sub
点击“SetMe”会产生编译器错误:变量未定义。将声明“Global1”的位置移到单独的模块中后,一切正常。 我的问题是:我所阅读的所有内容都说,在一个模块的顶部,在任何代码之外声明的全局变量应该对项目中的所有模块可见。显然情况并非如此。除非我对“模块”的理解不正确。随着工作簿一起提供的“Sheet1”、“Sheet2”、“ThisWorkbook”等对象:它们不是能够在全局范围内声明变量的模块吗?还是唯一可以声明全局变量的位置是类型为“模块”的单独模块?

我认为UserForms的代码属于模块类型,尽管它并没有被明确列为这样的类型。这个说法正确吗? - peege
@sancho.s 我删掉了它以避免混淆 :) 我错过了Pearson的链接,并且误解了我发布的MSDN链接中的一行。今天学到了新东西 :) - L42
您在这里找到了有用的答案吗? 给予反馈总是有益的,因为其他SO用户也可以看到。 - sancho.s ReinstateMonicaCellio
2个回答

26

您的问题是: 这些模块不能在全局范围内声明变量吗?

答案:可以,在全局范围内声明变量是“可行的”。

唯一的问题在于,对于ThisWorkbook或Sheet模块中的全局变量引用必须是完全限定的(例如,作为ThisWorkbook.Global1引用)。 在标准模块中,仅在存在歧义的情况下(例如,如果有多个标准模块定义了名称为Global1的变量,并且您想在第三个模块中使用它)才必须完全限定引用全局变量。

例如,在Sheet1中的代码中放置:

Public glob_sh1 As String

Sub test_sh1()
    Debug.Print (glob_mod)
    Debug.Print (ThisWorkbook.glob_this)
    Debug.Print (Sheet1.glob_sh1)
End Sub

将代码放置在 ThisWorkbook

Public glob_this As String

Sub test_this()
    Debug.Print (glob_mod)
    Debug.Print (ThisWorkbook.glob_this)
    Debug.Print (Sheet1.glob_sh1)
End Sub

并且在标准模块代码中

Public glob_mod As String

Sub test_mod()
    glob_mod = "glob_mod"
    ThisWorkbook.glob_this = "glob_this"
    Sheet1.glob_sh1 = "glob_sh1"
    Debug.Print (glob_mod)
    Debug.Print (ThisWorkbook.glob_this)
    Debug.Print (Sheet1.glob_sh1)
End Sub

所有的三个子函数都能正常工作。

PS1:这个答案主要基于这里提供的信息,非常值得一读(来自伟大的Chip Pearson)。

PS2:你的代码行Debug.Print("Hello")会给你编译错误Invalid outside procedure

PS3:你可以用VB编辑器中的调试->编译VBAProject部分地检查你的代码。所有编译错误都会弹出。

PS4:还可以查看将Excel-VBA代码放在模块或工作表中?

PS5:你可能无法在例如Sheet1中声明全局变量,并在其他工作簿的代码中使用它(阅读http://msdn.microsoft.com/en-us/library/office/gg264241%28v=office.15%29.aspx#sectionSection0;我没有测试这一点,所以这个问题仍然需要确定)。但是在你的例子中,这并不是你的意思。

PS6:在不完全限定全局变量的情况下,会有几种导致歧义的情况。你可以稍微调整一下来找到它们。它们是编译错误。


我在我发布的链接中误解了一行。今天学到了新东西:)。绝对+1。如果我可以投多次票,我会这样做的。 - L42
这真的让我发疯了 - 将“Public thing as New Thing”添加到模块中而不是添加到ThisWorkbook可以解决所有访问“thing.something()”时出现的“424”错误问题。 - oooyaya

4
你可以按照以下步骤来学习/测试这个概念:
  1. 打开新的Excel工作簿,在Excel VBA编辑器中右键点击“模块”->“插入”->“模块”

  2. 在新增的Module1中添加声明:Public Global1 As String

  3. 在工作表VBA模块Sheet1(Sheet1)中放置代码片段:

Sub setMe()
      Global1 = "Hello"
End Sub
在工作表VBA模块Sheet2(Sheet2)中放置以下代码片段:
Sub showMe()
    Debug.Print (Global1)
End Sub
  1. 按顺序运行 Sub setMe() 和 Sub showMe(),以测试变量 Global1 的全局可见性/可访问性。

希望这能有所帮助。


1
简单易懂,谢谢,对我很有用。我已经命名了一个模块为“Globals”,并且只用它来定义全局变量 - 没有子程序、函数或任何代码在其中,只有定义的全局变量。 - Tin Bum
不客气!很高兴它对你有用。如果你对解决方案感到满意,请标记答案为已接受。最好的问候, - Alexander Bell

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