Mathieu Guindon
Mathieu Guindon

Reputation: 71207

Can UDT's be used as method parameters in any way?

For years I've been avoiding the use of Public Type UDT's in VBA, because they're hard to pass around and I never really bothered trying to understand why.. until now - it was simply easier to just create a class module and work with actual objects instead.

But recently I gave it a shot, and once I figured they had to be passed ByRef (as an array would), things started to look like I could start using them.

So I defined a Public Type in a standard module, got this compile error:

Only public UDT's defined in a public object module can be used as a parameter for public procedures of class modules

So I moved the Public Type into a class module, made the class PublicNotCreatable, and then got this compile error:

Cannot define a public UDT in a class module


Here's some code to reproduce the compile error.

Class module "Something":

Option Explicit
' cannot define a public user-defined type within an object module
Public Type TSomething
    Foo As Integer
End Type

Public Function Create(ByRef info As TSomething) As Something
End Function

If you move the definition of TSomething to a standard module, you'll get the other compiler error, telling you that the public UDT must be defined in a public object module (i.e. a class module)... which takes you back to square one.


So if you cannot define a Public Type in a class module, why would the compiler throw a fit and even mention "public user defined types defined in public object modules" if such a thing can't legally exist?

Did it work in VB6 and the compiler message is a remnant of that version? Or is the reason somewhere in how COM works? Is it just me or the two error messages are contradicting each other? Or there's something I'm not understanding?

Obviously I'm misusing/abusing UDT's here. So what are they supposed to be used for, if not for passing a "record" to some method?

Upvotes: 3

Views: 549

Answers (2)

ThunderFrame
ThunderFrame

Reputation: 9461

Here's a Type being passed as a parameter to a class method, and being returned by a class method.

First the class SomeClass (doesn't need to be PublicNotCreatable)

Option Explicit

Sub test(foo As TFooBar)
  Dim s As String
  s = foo.foo
End Sub

Function ReturnTFoo() As TFooBar
  ReturnTFoo.bar = "bar"
  ReturnTFoo.foo = " bar"
End Function

And the Module:

Option Explicit

Public Type TFooBar
  foo As String
  bar As String
End Type

Sub test()
  Dim c As SomeClass
  Set c = New SomeClass
  Dim t1 As TFooBar
  Dim t2 As TFooBar
  t1.bar = "bar"
  t1.foo = "Foo"
  c.test t1

  t2 = c.ReturnTFoo
End Sub

Upvotes: 1

cyboashu
cyboashu

Reputation: 10433

From standard module it works without any error. Following code threw no error.

Public Type TEST_TYPE
    Prop1   As String
End Type

Public Function fTest(ByRef param1 As TEST_TYPE) As String
    param1.Prop1 = "Hello from function"
End Function

Public Sub sTest(ByRef param1 As TEST_TYPE)
    param1.Prop1 = "Hello from Sub"
End Sub

Public Sub caller()

    Dim p   As TEST_TYPE

    '/Call Sub
    Call sTest(p)

    MsgBox p.Prop1

    '/Call Function
    Call fTest(p)

    MsgBox p.Prop1

End Sub

One issue with UDT is about Forward referencing. So this will not compile, apart from that It works perfectly fine with standard modules.

Public Type TEST_TYPE
    Prop1   As String
    Prop2   As TEST_TYPE2 '/ Fails due to Forward referencing. TEST_TYPE2 should be declared before this UDT.
End Type

Public Type TEST_TYPE2
    Prop3   As String
End Type

Edit:

However, the work around to use the UDT in class is Friend

VBA Code for Class

'/ Using UDT in VBA-Class
Private Type TEST_TYPE3
    Prop3   As String
End Type

Public Sub caller()

    Dim p As TEST_TYPE3
    p.Prop3 = "Hello from Class"
    Call testClassUDT(p)

End Sub

Friend Sub testClassUDT(p As TEST_TYPE3)
    MsgBox p.Prop3
End Sub

Upvotes: 3

Related Questions