正在 class objects 的 collection 中加载 table 值

Loading table values inside a collection of class objects

我正在努力使用 vba class 语法。 我有一个 table 向我显示一种联系人簿,其中包含名称、姓氏、街道和邮编。当一个人有多个地址时,会有一个没有名字和姓氏但有新街道和邮编的新行。

我正在尝试将所有数据存储在 collection 中,其中包含人员和地址 class。

在我的模块中,我尝试在 collection 中加载 table。在第一个 if 分支 中,我确保该行的第一个单元格不为空,这意味着它是一个新人,所以我需要创建一个新的 collection物品。 在 else 分支 中,我在该行的第一个单元格为空时输入,这意味着它只是我需要添加到前一个 collection 项目的地址。 我做错了什么?

代码 运行 在我的 for 循环的第一次迭代中是正确的,但随后它卡在了循环的第二个 运行 上,在我的 class_terminate 上停止了人 class.

我在 collection 中存储数据的方式是否正确?

地址

Option Explicit

Private pStreet As String
Private pZip As Integer

Public Property Let Street(val As String)
   pStreet = val
End Property
Public Property Get Street() As String
   Street = pStreet
End Property
Public Property Let Zip(val As Integer)
   pZip = val
End Property
Public Property Get Zip() As Integer
   Zip = pZip
End Property

Private pName As String
Private pSurname As String
Private pAddresses As New Collection

Public Property Let Name(val As String)
    pName = val
End Property
Public Property Get Name() As String
    Name = pName
End Property

Public Property Let Surname(val As String)
    pSurname = val
End Property
Public Property Get Surname() As String
    Surame = pSurname
End Property

Private Sub Class_Initialize()
    Set pAddresses = New Collection
End Sub

Private Sub Class_Terminate()
    Set pAddresses = Nothing
End Sub

Public Sub addAddress(ByVal val As Address)
    pAddresses.Add val
End Sub

Public Property Get Addresses() As Collection
    Set Addresses = pAddresses
End Property

Public Property Get Address(ByVal Index As Long) As Address
    Set Address = pAddresses(Index)
End Property 

人物工厂

Option Explicit

Public Function Create(ByVal Name As String, ByVal Surname As String, ByVal Street As String, ByVal Zip As Integer) As person
   Dim a As Address
   
   Set Create = New person
   Create.Name = Name
   Create.Surname = Surname
   
   Set a = New Address
   a.Street = Street
   a.Zip = Zip
   Create.Addresses.Add a
   
   Set Create = Nothing
   Set a = Nothing
   
End Function

模块测试

Private Sub testFilter()

    Dim nameCol, surnameCol, streetCol, zipCol As Integer

    nameCol = 1
    surnameCol = 2
    streetCol = 3
    zipCol = 4

    Dim coll As New Collection
    Sheets.Item("contacts").Select
    
    For i = 2 To getLastRow
        If Cells(i, nameCol).Value <> "" Then
            k = k + 1
            Dim pf As PersonFactory
            Dim p As person
            Set pf = New PersonFactory
            Set p = pf.Create(CStr(Cells(i, nameCol).Value), CStr(Cells(i, surnameCol).Value), CStr(Cells(i, streetCol).Value), CInt(Cells(i, zipCol).Value))
            coll.Add p
            
            Set pf = Nothing
            Set p = Nothing
        Else
            Dim addr As Address
            Set addr = New Address
            addr.Street = CStr(Cells(i, streetCol).Value)
            addr.Zip = CInt(Cells(i, streetCol).Value)
            coll.Add addr
            
            Set addr = Nothing
        End If
    Next
End Sub

我对您的 test-module 进行了一些重构 - 查看内联评论

Option Explicit

Private Enum en_colTable
    'value of enums are automatically increased by 1
    'if you change the order the value changes as well
    nameCol = 1
    surnameCol
    streetCol
    zipCol
End Enum


Private Sub testFilter()

    Dim colPersons As New Collection    'this name is more explicit about what the collection is
    
    Dim ws As Worksheet
    Set ws = Thisworkbook.Worksheets.Item("contacts")    'use a worksheet variable to be more explicit
    
    Dim pf As personFactory
    Dim p As person, addr As Address
    
    Set pf = New personFactory  'you need to do this only once
    
    Dim i As Long
    With ws
        For i = 2 To getLastRow
            If .Cells(i, nameCol).Value <> "" Then
                Set p = pf.Create(CStr(.Cells(i, nameCol).Value), _
                                 CStr(.Cells(i, surnameCol).Value), CStr(.Cells(i, streetCol).Value), CInt(.Cells(i, zipCol).Value))
                colPersons.Add p
                
            Else
                Set addr = New Address
                addr.Street = CStr(.Cells(i, streetCol).Value)
                addr.Zip = CInt(.Cells(i, streetCol).Value)
                p.Addresses.Add addr    'add address to person
            End If
        Next
    End With
End Sub

关于 ParentFactory: 您一定不能将那些创建的对象设置为空!!!

父工厂

Option Explicit

Public Function Create(ByVal Name As String, ByVal Surname As String, ByVal Street As String, ByVal Zip As Integer) As Person
   Dim a As Address
   
   Set Create = New Person
   Create.Name = Name
   Create.Surname = Surname
   
   Set a = New Address
   a.Street = Street
   a.Zip = Zip
   Create.Addresses.Add a
   
' Do not set these variables to nothing - if so they don't exist anylonger!!!!
'   Set Create = Nothing
'   Set a = Nothing
   
End Function