View Full Version : collection issue with custom type variable
JimmyTheHand
06-16-2008, 02:16 PM
Hi
See the code below:
 Type MyType
    a1 As String
    a2 As Variant
End Type
Sub test()
    Dim Col As Collection, Itm As MyType
    Set Col = New Collection
 Col.Add Itm
End Sub I want to put custom type variables into a collection, but at the red line I get this horrible error message:
"Only public user defined types defined in public object modules can be used as  parameters or return types for public procedures of class modules or as fields  of public user defined types"
 On my level of knowledge this error message is cryptic. Nevertheless I looked for solutions that I may be able to implement, but they suggest everywhere that I create a dll. Which I don't want to, because I don't know how to do it yet, and right now I think it would be too much fuss to learn it for such a small task.
I hope someone knows an easier solution? Or a workaround? 
I would be very grateful for it--:help : pray2::help
Jimmy
Bob Phillips
06-16-2008, 02:37 PM
I know I will be ploughing a lone furrow, but ditch UDTs, ditch collectuions, and build a collection class.
mikerickson
06-16-2008, 06:22 PM
Collections do not accept custom data types. 
Neither can UDT's be assigned to Variant variables.
You could use an array if you had to, but it would have to be typed as MyType, not Variant, which limits what you can do with it. (Can't return an array of UDTs from a function.)
I agree with XLD, use a Class rather than UDT.
BTW, what is a "dll"?
JimmyTheHand
06-16-2008, 11:07 PM
I know I will be ploughing a lone furrow, but ditch UDTs, ditch collectuions, and build a collection class. 
:wot
Well... umm...All right, Bob...
There's only two things I didn't understand.
#1 - "ploughing a lone furrow"
#2 - collection class
For #1, I have found a "solution" in a reasonably short time, though it's still a bit confusing. According to the idiom dictionary,  you think you are in for a long work, alone, with no help from others. My first bet was that you think nobody will share your opinion? 
I know it's irrelevant from my original question's point of view, but I'm still curious what your meaning was.
For #2, I guess I just have to find it out for myself. Mike has kindly confirmed this path, and also shed a little light on it by illuminating that "collection class" is not an occult piece of magic artifact, but a type of classes. I've got somewhat familiar with classes these last months.
    
Collections do not accept custom data types.
Neither can UDT's be assigned to Variant variables.
Can't return an array of UDTs from a function.  
Wonder why is that. If memory serves, I had no such problems with Delphi. Anyway, your explanation is much easier to understand than the error message I got. :thumb
 BTW, what is a "dll"? "Dynamic link library", I guess. I found such suggestions on forums dealing with VB in general, not Excel and VBA, but thought it still held for my problem.
Bob, Mike, thank you both for putting me on the right path. For the moment I'm going to use an array of UDTs, which is suitable for my purposes, so that I can proceed with my project. In the meantime I will learn about collection classes and replace those arrays when I'm ready.
Jimmy
Bob Phillips
06-16-2008, 11:46 PM
BTW, what is a "dll"?
Dynamic linked library. It is a shared library in MS windows terms, where you put the code that many applications use. They are everywhere in windows, is it not the same on the Mac?
mikerickson
06-16-2008, 11:55 PM
From my VBE Help system:
dynamic-link library (DLL)
Applies to Windows only. A library of routines loaded and linked into applications at run time.
Note   The Macintosh operating system convention is a code fragment or shared library.
It sounds like Mac shares routines differently. 
I like to write algorithms, but I'm not very computer savy. I don't know much about this stuff.
Bob Phillips
06-17-2008, 12:01 AM
It is very straight-forward. YOu create two classs, one for the object, MType, and one for a collection of MTypes.
The MType class is very simple
Option Explicit
Private mA1 As String
Private mA2 As Variant
Public Property Let A1(ByVal Val As String)
    mA1 = Val
End Property
Public Property Get A1() As String
    A1 = mA1
End Property
Public Property Let A2(ByVal Val As String)
    mA2 = Val
End Property
Public Property Get A2() As String
    A2 = mA2
End Property
Public Function Name()
    Name = mA1 & " " & mA2
End Function
Note that I have created two properties, the eelements of your UDT, and a simple function to process them. An example of using these would be
Sub TestClass()
Dim mpType As mType
    Set mpType = New mType
    mpType.A1 = "Jimmy"
    mpType.A2 = "The Hand"
    MsgBox mpType.Name
    
    Set mpType = Nothing
End Sub
Bob Phillips
06-17-2008, 12:46 AM
And here it gets interesting, when you add the collection class. Unfortunately, you have to hand-crank all of the collection methods, like Add, remove, and enumerate.
I added an id to the MType class first
Option Explicit
 
Private mcA1 As String
Private mcA2 As Variant
Private mcId As String
 
Public Property Let Id(ByVal Val As String)
    mcId = Val
End Property
Public Property Get Id() As String
    Id = mcId
End Property
 
Public Property Let A1(ByVal Val As String)
    mcA1 = Val
End Property
Public Property Get A1() As String
    A1 = mcA1
End Property
 
Public Property Let A2(ByVal Val As String)
        mcA2 = Val
End Property
Public Property Get A2() As String
A2 = mcA2
End Property
 
Public Function Name()
    Name = mcA1 & " " & mcA2
End Function
and the collection class, MTYpes, looks like
Option Explicit
Private mcTypes As Collection
Function NewEnum() As IUnknown
    Set NewEnum = mcTypes.[_NewEnum]
End Function
Public Function Add(ThisType As MType)
    If Not ExistsInCollection(mcTypes, ThisType.Id) Then
        mcTypes.Add ThisType, ThisType.Id
    End If
End Function
Public Property Get Count() As Long
    Count = mcTypes.Count
End Property
Public Property Get Items() As Collection
    Set Items = mcTypes
End Property
Public Property Get Item(Index As Variant) As MType
    Set Item = mcTypes(Index)
End Property
Public Sub Remove(Index As Variant)
    mcTypes.Remove Index
End Sub
Private Sub Class_Initialize()
    Set mcTypes = New Collection
End Sub
Private Sub Class_Terminate()
    Set mcTypes = Nothing
End Sub
'--------------------------------------------------------------------------
Public Function ExistsInCollection(pColl, ByVal pKey As String) As Boolean
'--------------------------------------------------------------------------
    On Error GoTo NoSuchKey
    If VarType(pColl.Item(pKey)) = vbObject Then
         ' force an error condition if key does not exist
    End If
    ExistsInCollection = True
    Exit Function
     
NoSuchKey:
    ExistsInCollection = False
End Function
You can then use it as in this example
Option Explicit
Public Sub AddToDirectoryClass2()
Dim mpTypes As MTypes
Dim mpType As MType
    Set mpTypes = New MTypes
    
    Set mpType = New MType
    With mpType
    
        .Id = "JTH"
        .A1 = "Jimmy"
        .A2 = "The Hand"
        mpTypes.Add mpType
    End With
    Set mpType = Nothing
    
    Set mpType = New MType
    With mpType
    
        .Id = "RP"
        .A1 = "Bob"
        .A2 = "Phillips"
        mpTypes.Add mpType
    End With
    Set mpType = Nothing
    
    Call TypeDetails(mpTypes)
    
    mpTypes.Remove "JTH"
    
    Call TypeDetails(mpTypes)
   
    Set mpTypes = Nothing
End Sub
Public Sub TypeDetails(Optional Types As MTypes)
Dim mpType As MType
Dim mpMsg As String
    
    mpMsg = "Number of Types =  " & Types.Count & vbNewLine & vbNewLine & _
            "Types.Item(1).id = " & Types.Item(1).Id & vbNewLine & vbNewLine
    MsgBox mpMsg, vbInformation, "Class demo"
    
    For Each mpType In Types.Items
       mpMsg = mpType.Name
       MsgBox mpMsg, vbInformation, "Class demo"
    Next mpType
    
End Sub
As I say, a lot more code to set it up, but tons more flexible when done.
JimmyTheHand
06-17-2008, 01:10 AM
As I say, a lot more code to set it up, but tons more flexible when done. 
And also a lot of code to prod through. Bob, you gave me reading matter for the next few weeks!! :eek:
I'm going to study this, and when I create my first Collection Class, I'll send you a complimentary copy :thumb
Thanks :friends:, 
Jimmy
PS:
OMG, I'm really overwhelmed by this code...
I'll be back with further questions if I get stuck.
Bob Phillips
06-17-2008, 02:20 AM
It's all pretty straight-forward Jimmy, once you get into it. Start with my first post and reconcile that to your MType UDT. Then move on to the second post (that is why I did two postings to differentiate them).
I think we covered this in a previous post of yours, I just didn't give you the code then.
The only cool thing there is the collection enumeration, I haven't seen that published anywhere else, but is a basic requirement in collections IMO, and certainly adds to their flexibility.
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.