3

I have a table, and I want to convert each row from that table in an object. The object will have properties for each column.

I made this function:

Public Function GetProducts() As Object
   Set GetProducts = New Collection

    Dim p As New ProductInfo
    Dim rng As Range
    Dim xRow As Range

    Set rng = Sheet2.Range("A2:I" & Sheet2.Range("A2").End(xlDown).Row)

        For Each xRow In rng.Rows

            p.Id = xRow.Cells(1, 1).Value
            p.Cod = xRow.Cells(1, 2).Value
            p.Name = xRow.Cells(1, 3).Value
            p.productType = xRow.Cells(1, 4).Value
            p.norma = xRow.Cells(1, 5).Value
            p.masina = xRow.Cells(1, 6).Value
            p.masinaType = xRow.Cells(1, 7).Value
            p.operatori = xRow.Cells(1, 8).Value
            p.sectie = xRow.Cells(1, 9).Value

            GetProducts.Add Item:=p, Key:=CStr(p.Id)

        Next xRow

End Function

than I tried to check the function with this Sub:

Public Sub CheckProducts()
    Dim products As Collection
    Dim p As ProductInfo
    Set products = GetProducts()

        For Each p In products
            MsgBox p.Id
        Next p

End Sub

The msgbox is returning always 20 (I have 20 items in my table, and last ID is 20).

When I checked the number of items in collection, I got 20, as I was expected.

Can anyone help me understand why I cannot iterate the collection and get the id of each item?

Lucian Bumb
  • 2,821
  • 5
  • 26
  • 39
  • Mind posting your code for ProductInfo? And dumb obvious question - column A does have unique values doesn't it? – Absinthe Mar 16 '17 at 09:16

1 Answers1

6

In GetProducts() you need to code:

Dim p As ProductInfo

And not:

Dim p As New ProductInfo

And then in the loop code:

Set p = New ProductInfo

Here's an example:

Data

enter image description here

Class - TestInfo

Private m_Id As String
Private m_Code As String
Private m_Name As String

Property Get Id() As String
    Id = m_Id
End Property
Property Let Id(str As String)
    m_Id = str
End Property

Property Get Code() As String
    Code = m_Code
End Property
Property Let Code(str As String)
    m_Code = str
End Property

Property Get Name() As String
    Name = m_Name
End Property
Property Let Name(str As String)
    m_Name = str
End Property

Module

Option Explicit

Sub Test()
    Dim coll As Collection
    Dim obj As TestInfo

    Set coll = GetProducts

    For Each obj In coll
        MsgBox obj.Name
    Next
End Sub

Public Function GetProducts() As Collection

    Set GetProducts = New Collection

    Dim rngData As Range
    Dim lngCounter As Long
    Dim obj As TestInfo '<--- do not use New here

    Set rngData = ThisWorkbook.Worksheets("Sheet1").Range("A1:C7")

    For lngCounter = 2 To rngData.Rows.Count
        Set obj = New TestInfo '<--- use New here

        obj.Id = rngData.Cells(lngCounter, 1).Value
        obj.Code = rngData.Cells(lngCounter, 2).Value
        obj.Name = rngData.Cells(lngCounter, 3).Value

        GetProducts.Add obj

    Next lngCounter

End Function

Note

And also I personally would not use this statement:

Set GetProducts = New Collection

Instead I would do:

Public Function GetProducts() As Collection

    Dim coll As Collection
    Dim rngData As Range
    Dim lngCounter As Long
    Dim obj As TestInfo

    Set rngData = ThisWorkbook.Worksheets("Sheet1").Range("A1:C7")
    Set coll = New Collection

    For lngCounter = 2 To rngData.Rows.Count
        Set obj = New TestInfo
        obj.Id = rngData.Cells(lngCounter, 1).Value
        obj.Code = rngData.Cells(lngCounter, 2).Value
        obj.Name = rngData.Cells(lngCounter, 3).Value
        coll.Add obj
    Next lngCounter

    Set GetProducts = coll

End Function

Why?

There's a good few Q&A on stackoverflow to read and consider:

Community
  • 1
  • 1
Robin Mackenzie
  • 18,801
  • 7
  • 38
  • 56