我可以在了解Excel 2013 VBA模块中使用Public vs Dim方面提供一些帮助。
首先,我想说的是,我确实找到了具有出色定义的出色文章(请参见下面的链接),但是没有示例,我可以使用一些示例来说明如何将公共变量应用于我的项目。另外,我对何时需要使用Option Private Module感到困惑。我需要在拥有的每个模块上还是仅在包含以下代码的模块上使用它?
stackoverflow descriptions difference between Public/Private
我想做的是在Standard Mod中进行设置,因此我不必继续通过我的所有用户窗体为工作表设置变量,这些用户窗体对它们引用的工作表使用相同的命名约定。
Sub PubVar()
Public wb As Workbook
Public wsSI As Worksheet
Public wsRR As Worksheet
Public wsCalcs As Worksheet
Public wsNarr As Worksheet
Public wsEval As Worksheet
Public wsUW As Worksheet
Public wsLVBA As Worksheet
Set wb = Application.ThisWorkbook
Set wsSI = wb.Sheets("SavedInfo")
Set wsCalcs = wb.Sheets("Calcs")
Set wsNarr = wb.Sheets("Narrative")
Set wsEval = wb.Sheets("EvalCL")
Set wsUW = wb.Sheets("UWCL")
Set wsLVBA = wb.Sheets("ListsForVBA")
End Sub
谢谢您的帮助。
答案 0 :(得分:2)
Option Private Module
应该在任何不希望将其公共成员作为宏(即Public Sub
过程)或用户定义函数(即{{1})公开给Excel的标准模块中使用。 }程序)。
没有此选项,标准模块的公共无参数Public Function
过程将显示在Excel的可用宏列表中,而公共Sub
过程将在Excel的单元格“ intellisense”中显示为可用的工作表函数。
请注意,这只是从宏列表中隐藏一个模块的成员:如果您键入“隐藏”过程的确切名称,Excel仍将运行它。
Function
是一个关键字,用于在过程范围内声明局部变量。关键字也是 legal ,用于声明私有的模块级变量,但是您最好使用Dim
。
当用于声明模块级变量时,Private
使得该变量只能从在其声明的模块内部访问。
在声明模块级变量时,Private
使该变量可以从任何有权访问其声明的模块的对象中访问-在标准模块中,这意味着该变量实际上是Public
。在类(/ document / userform /其他)模块中,这意味着变量具有实例状态,并且可以从有权访问该类实例的任何人访问。带有 predeclaredId 的类,例如Global
类,都具有可全局访问的实例:避免在此默认实例中存储实例状态。
UserForm
Set wb = Application.ThisWorkbook
Set wsSI = wb.Sheets("SavedInfo")
Set wsCalcs = wb.Sheets("Calcs")
Set wsNarr = wb.Sheets("Narrative")
Set wsEval = wb.Sheets("EvalCL")
Set wsUW = wb.Sheets("UWCL")
Set wsLVBA = wb.Sheets("ListsForVBA")
是您正在查看的工作簿-包含您的VBA代码的工作簿。 ThisWorkbook
标识符可全局访问,ThisWorkbook
只是指向该对象的指针。
在Application.ThisWorkbook
上使用ThisWorkbook
,除非您已声明局部变量并将其命名为Application.ThisWorkbook
-否则该局部变量将成为 shadowing 全局标识符;不要那样做
ThisWorkbook
符合ThisWorkbook
的条件。
现在,如果在编译时Application
中存在这些工作表中的任何一个,则您不需要任何这些变量。在 Project Explorer (Ctrl + R)中找到每个工作表,然后按F4并为其ThisWorkbook
属性赋予一个有意义的标识符名称。
因此,如果您将(Name)
重命名为Sheet1
,则可以从代码中的任何位置访问SavedInfoSheet
,而无需从{{1}取消引用}(或更好的SavedInfoSheet
)集合。这样做的原因是,VBA会根据您放置为Workbook.Sheets
模块的Workbook.Worksheets
属性的任何标识符的名称自动创建一个全局范围的标识符。
如果工作表在编译时不存在(即它们是在运行时创建的),那么您也不需要这些变量,因为创建它们的代码应该已经具有该引用:>
(Name)
然后,您可以(并且应该)根据需要传递这些工作表对象引用作为参数。
我想做的是在Standard Mod中进行设置,因此我不必继续通过我的所有UserForm来为工作表设置变量,这些用户窗体对它们引用的工作表使用相同的命名约定 < / p>
您的表单正在运行该节目。激发他们的代码如下:
Worksheet
像任何UI一样,表单负责收集用户输入,并向用户显示数据。如果您发现自己在编写用户窗体代码,并访问了十几个工作表(和/或更糟糕的是,makes them public fields),则说明您的表单变得非常复杂,很多 ,并且您通过将其默认实例设为有状态,将成熟的对象作为过程的纯容器进行处理。
This article详细介绍了如何解决该问题。 This article进一步推动了这一概念的发展,并允许 view 和 presenter 之间来回通信,并提供了一个下载链接和一个简单的示例进行研究(免责声明:我写了这些文章以及随附的示例代码。
UserForm代码做得正确,看起来非常简单,并且只负责很少的逻辑,这很无聊。实际上,它不负责除表示之外的任何逻辑-UserForm要做的所有事情,响应控制事件,将控制状态中继到某些模型,并且如果需要在关闭表单之前执行应用程序逻辑(例如,如果单击了命令按钮,但表单应保持打开状态),则它将触发一个事件,并且调用代码(“演示者”)通过触发来处理该事件需要运行的逻辑。
对话正常后,或将事件中继给 presenter 时,将执行表单后面代码的代码 outside 执行到工作:表单永远不会需要了解任何工作表。
答案 1 :(得分:-1)
如果您要制作自己的Excel加载项(* .XLAM文件),则实际上只需要Option Private Module
。它允许该模块的Public
变量对加载项自己的项目中的其他模块可见,但使其他使用您的AddIn的工作表不可见/调用它们。
至于其他,不清楚您要问什么。您链接的问题很好地解释了Public vs Dim / Private。 VBA代码无法在同一VBA项目中的不同模块,表单或类中看到私有/昏暗变量。如果您希望所有的VBA代码都能看到/调用它,则可以使用public。如果希望只在其自己的模块中可见/可调用它,则可以使用private / dim。
但是通常您要对公开的内容保持审慎,因为这会给您太多的全局名称(令人困惑),可能导致名称重复(问题,可以通过以下方式解决)命名标准),最重要的是因为它可能导致令人困惑/晦涩的错误和可怕的调试问题(因为任何公共变量更改都可能导致任何其他代码可以看到其行为不同)。有些事情比其他事情更糟糕:
Public Subs OK in a module, but better in a Class
Public Function Usually fine, especially if its a true function
Public Const No problem, belongs in modules
Public Variables Very Bad. *UNLESS ...*
公共变量是优秀程序员担心的变量。应避免使用它们,除非它们是我们所谓的“只读变量”。这些变量您只需设置一次,就不会再更改。只要遵循该规则,它们实际上就是常量并且可以(尽管只读静态属性会更好,但是VBA在这方面有太多限制)。
最后,如果您想对所有代码中可见/可用的所有工作表都使用命名变量,但只需要设置一次即可,这就是Public
的作用,但声明(“ ”)必须位于“ 模块级别”,这意味着在模块中,但在任何子例程或函数之外。像这样:
Public wb As Workbook
Public wsSI As Worksheet
Public wsRR As Worksheet
Public wsCalcs As Worksheet
Public wsNarr As Worksheet
Public wsEval As Worksheet
Public wsUW As Worksheet
Public wsLVBA As Worksheet
' sets all of the Worksheet variables
Sub PubVar()
Set wb = Application.ThisWorkbook
Set wsSI = wb.Sheets("SavedInfo")
Set wsCalcs = wb.Sheets("Calcs")
Set wsNarr = wb.Sheets("Narrative")
Set wsEval = wb.Sheets("EvalCL")
Set wsUW = wb.Sheets("UWCL")
Set wsLVBA = wb.Sheets("ListsForVBA")
End Sub