VBA - 试图了解如何调用类模块

Posted

技术标签:

【中文标题】VBA - 试图了解如何调用类模块【英文标题】:VBA - Trying to understand how to call Class Modules 【发布时间】:2020-09-15 17:49:28 【问题描述】:

我正在通过 Google、YouTube 等学习 VBA。我遇到了 Class Modules。

我有一个Tracker Template。 每隔几天我就会收到一份报告 ("Ice cream FG Inv.xlsm")

在尝试理解Class Modules 时,我发现了一个模板,该模板创建了一个类模块(在跟踪器模板中)WBIceCreamFGINVxlsm,为Ice Cream FG Inv.xlsm Workbook 中的所有工作表创建了一个代码名。

例子:

Public Property Get wsinventory() As Worksheet
    Set wsinventory = Workbook.Worksheets("Inventory")
End Property

在我的模块中,我想引用 wsinventory,但不了解如何“调用”类模块..

两个工作簿都是打开的。

我试着从:

Dim Data As Variant
    Data = wsinventory.Range("A1").CurrentRegion.Value   (**Variable not Defined**)

然后我尝试了:

Dim wsinventory As Worksheets
With wsinventory
    Dim Data As Variant
        Data = .Range("A1").CurrentRegion.Value (**Object variable or With variable not set**)
End With

我还需要使用吗:

Dim DataSource As Workbook
Set DataSource = Workbooks("Ice Cream FG Inv.xlsm")
    With DataSource.Worksheets("Inventory")
    End With

如果是这样,使用类模块的原因是什么?

【问题讨论】:

看来你过于复杂了。 我很有可能!我疯狂地在谷歌上搜索 VBA,试图找到最好/有效的做事方式。所以,什么时候可以使用类模块。 不是这个场合...我会先专注于学习 Excel 对象模型。 相关或重复:***.com/a/1740020/13813219 【参考方案1】:

您需要先创建一个类对象,然后才能访问该类的属性。

假设你有这个类并将其命名为TestClass

Private pwsinventory As Worksheet

Public Sub init()
    Set pwsinventory = Worksheets("Inventory")
End Sub

Public Property Set wsinventory(lwsinventory As Worksheet)
    Set pwsinventory = lwsinventory
End Property

Public Property Get wsinventory() As Worksheet
    Set wsinventory = pwsinventory
End Property

您可以像这样设置/获取属性:

Sub test()
    Dim datacls As TestClass
    Dim data As Worksheet
    
    Set datacls = New TestClass
    Set datacls.wsinventory = Worksheets("inventory")
    Set data = datacls.wsinventory
    
    Debug.Print data.Name
End Sub

然而,这有点奇怪,当你有一个不想设置的属性(你需要传递一个参数)时,你应该使用一个启动函数。不幸的是,如果不在创建类对象后手动调用该 sub,我就无法做到这一点。

Sub Test2()
    Dim datacls As TestClass
    
    Set datacls = New TestClass
    
    datacls.init
    
    Debug.Print datacls.wsinventory.Name
End Sub

我使用类的最常见情况是更好的容器。通常在数组/字典中存储许多相同的类类型,因此很清楚我在调用什么,特别是如果我需要为每个实例以相同的方式修改数据。

【讨论】:

【参考方案2】:

我将再举一个例子。创建一个类定义并命名为ArrayData,并定义多个初始化子程序

ArrayData.cls

Private m_data() As Variant

Private Sub Class_Initialize()
        
End Sub

Public Sub IntializeEmpty(ByVal rows As Long, ByVal columns As Long)
    ReDim m_data(1 To count, 1 To columns)
End Sub

Public Sub InitializeFromRange(ByRef target As Range)
    If target.rows.count > 1 Or target.columns.count > 1 Then
        m_data = target.Value2
    Else
        ReDim m_data(1 To 1, 1 To 1)
        m_data(1, 1) = target.Value
    End If
End Sub

Public Sub InitializeFromArray(ByRef data() As Variant)
    m_data = data
End Sub

Public Property Get RowCount() As Long
    RowCount = UBound(m_data, 1) - LBound(m_data, 1) + 1
End Property

Public Property Get ColCount() As Long
    ColCount = UBound(m_data, 2) - LBound(m_data, 2) + 1
End Property

Public Property Get Item(ByVal row As Long, ByVal col As Long) As Variant
    Item = m_data(row, col)
End Property
Public Property Let Item(ByVal row As Long, ByVal col As Long, ByVal x As Variant)
    m_data(row, col) = x
End Property

模块

要测试代码模块中的代码,请使用 New 关键字初始化类,然后调用自定义初始化子例程之一。

Public Sub TestArray()

    Dim arr As New ArrayData
    arr.InitializeFromRange Sheet1.Range("A2").Resize(10, 1)
    
    Dim i As Long
    For i = 1 To arr.RowCount
        Debug.Print arr.Item(i, 1)
    Next i

End Sub

PS。另请阅读this article,了解如何将一个属性指定为默认属性。在上面的示例中,如果Item 是默认属性,那么您可以编写如下代码

Debug.Print arr(5,2)

而不是

Debug.Pring arr.Item(5,2)

【讨论】:

以上是关于VBA - 试图了解如何调用类模块的主要内容,如果未能解决你的问题,请参考以下文章

试图了解模板类是如何工作的

如何实例化一个 vba 类并从 vb.net 调用一个方法?

在 Excel 公式中调用 VBA 类模块

vba如何调用dll中的过程函数或变量

vba如何写word

DLL文件制作与在VBA调用初级进阶