我可以将VBA模块作为参数传递给Sub / Function吗?

时间:2019-08-07 14:32:49

标签: excel vba

我正在尝试重构一些Excel VBA代码(Excel 2016,VBA 7.1),以消除出于维护目的的重复子例程。几个子例程的区别仅在于它们使用的全局常量组,所以我基本上想做的是将全局变量组合成一个类似struct的数据结构,这样我就可以将它们作为参数传递给一个通用函数。 / p>

请注意,全局常量组具有一些共同点,但不是全部,例如:

Global Const GROUP1_SHEET As String = "Sheet1"
Global Const GROUP1_FIRST_ROW As Long = 2
Global Const GROUP1_LAST_COL As Long = 15
Global Const GROUP1_SOME_COL_OFFSET = 4

Global Const GROUP2_SHEET As String = "Sheet2"
Global Const GROUP2_FIRST_ROW As Long = 2
Global Const GROUP2_LAST_COL As Long = 8
Global Const GROUP2_ANOTHER_COL_OFFSET = 2

每个组都有不同的子例程,例如:

在Sheet1中:

Private Sub DoSomething()
    Set w = Worksheets(GROUP1_SHEET)
    'some code
End Sub

在Sheet2中:

Private Sub DoSomething()
    Set w = Worksheets(GROUP2_SHEET)
    'same code as above
End Sub

有数十种。不用说,这段代码甚至是通宵阅读的噩梦,更不用说维护了。

我现在想要做的是将组分成单独的模块,并将它们设置为属性,类似于this question中所述。问题是我不知道如何将模块(即全局变量组)作为参数传递给函数。

在新模块GROUP1中:

Public Property Get SHEET() As String
    SHEET = "Sheet1"
End Property

这就像我想要的那样工作:

Public Sub ShowPopup()
    MsgBox GROUP1.SHEET
End Sub

但是将其作为参数传递不会:

Public Sub Popup(inModule As Object)
    MsgBox inModule.SHEET
End Sub

Public Sub ShowPopUp()
    Popup GROUP1
End Sub

在上面的示例中,我没有尝试替代“ Object”的方法。我会收到“ ByRef参数类型不匹配”或“期望的变量或过程,而不是模块”的信息,具体取决于我在此处输入的内容。

因此,我可以传递这样的模块(也许作为字符串并以某种方式对其求值吗?),还是应该使用其他方式对全局变量进行分组?

1 个答案:

答案 0 :(得分:2)

您不能将常规模块作为参数传递(从技术上讲,您可以传递字符串并使用Application.Run,但这可能是一场噩梦),但是您可以传递类。

类可以在全局范围内。因此,从技术上讲,您可以在某个时候实例化它(例如,打开一个工作簿),然后在任何时候使用它们。我会说在某些情况下全局变量是可以的,但是大多数时候您可以(也许应该)不用它们。我鼓励您研究一下全球范围的主题以及为什么它通常被认为是不好的。

您可以拥有这样的课程:

GroupClass:
Option Explicit
Private Type TypeGroup
    WS as WorkSheet
    FirstRow as Long
    FirstCol as Long
    ColumnOffset as Long
End Type
Private This as TypeGroup
Public Function Initialize(Byval WS as Sheet, Byval FirstRow as Long, ByVal FirstCol as Long, ByVal ColumnOffset as Long)
With This
    Set .WS = WS
    .FirstRow = FirstRow
    .FirstCol = FirscCol
    .ColumnOffset = ColumnOffset
End with
End Function
Public Property Get Name() as String
    Name = This.WS.Name
End Property

然后您可以像这样使用它:

Public Sub Popup(Group As GroupClass)
    MsgBox Group.Name
End Sub

Public Sub ShowPopUp()
    Dim Group1 as GroupClass
    Set Group1 = New GroupClass
    Group1.Initialize Worksheets("Sheet1"),2,15,4
    Popup Group1
End 

我使用Private TypePrivate This as TypeGroup can be found here的原因。类实例化的一些警告可能是seen here。根据您的工作,您的班级组织可能会非常不同。您可以阅读接口,不变性,何时使用getter / setter,封装和其他主题。