excel - 我可以将 VBA 模块作为参数传递给子/函数吗?

标签 excel vba

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

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

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

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

在工作表 1 中:

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

在工作表2中:

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

我尝试过的任何方法都无法代替上面示例中的“对象”。我要么得到“ByRef 参数类型不匹配”,要么得到“预期变量或过程,而不是模块”,具体取决于我放在那里的内容。

那么,我可以传递这样的模块(也许作为字符串并以某种方式对其进行评估?),或者我应该使用其他方式对全局进行分组?

最佳答案

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

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

你可以有这样的类(class):

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 。根据您所做的事情,您的类(class)组织可能会非常不同。您可以在其他地方阅读接口(interface)、不变性、何时使用 getter/setter、封装和其他主题。

关于excel - 我可以将 VBA 模块作为参数传递给子/函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57396816/

相关文章:

excel - 如何从Excel VBA中的注释形状对象获取单元格地址?

excel - 我可以与 CVErr() 一起使用什么错误号来指示 Access VBA 函数不会返回任何值?

excel - 如何从 Excel 工作簿中删除自定义工具栏?

vba - Excel VBA : MoviesByGenre Function

vba - Word VBA获取项目是不可见的错误

mysql - 将数据从矩阵转换为向量格式

vba - 使用 Excel VBA 将单个工作簿拆分为包含多个工作表的多个工作簿

VBA 和 Excel : Why does my TRIM script results in #VALUE on large data sets?

vba - 将行复制并粘贴到新工作表中,并根据其他单元格值更改单元格值(月份)

VBA 一周中各天之间的值求和