【问题标题】:VBA - Trying to understand how to call Class ModulesVBA - 试图了解如何调用类模块
【发布时间】: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 对象模型。

标签: excel vba


【解决方案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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-14
      • 2010-12-30
      相关资源
      最近更新 更多