Distinguish LO Basic Built in Objects for User Objects

I am trying to write a function (TypeNameEx) which will return a string which, using a call to VarType(), effectively identifies the type of a a (variant) variable, eg VarType 2 returns “integer” and VarType 3 returns “Long”.
All is fine until I get to VarType 9 which is an object. I COULD just return “Object” and have done with it but would rather something more specific. To this end, I have been able to work out how to establish if it is a UNO object and return “Object-UNO” but, beyond that, have been unable to make a distinction between one of LO’s built in objects or a user object (as defined in a Class Module). For my own Class Modules, I can give all of my classes a .MyClass property but I cannot do the same for class modules written/supplied by AN Other, is there a way to separate built-in objects from user objects?

I have included my code so far below, it is IsIntrinsicObject which I am stuck on

Function IsIntrinsicObject(ByRef rvarObject As Variant) As Boolean

  'Return the result of a test for a property method or name which a built in'
  ' object will have but a user object will not have.'
  'As I understand that there no particular property method or name which is'
  ' owned by ALL built-in non-UNO objects, this probably boils down ta a '
  ' large Select Case statement which tests a number of things'

End Function 'IsIntrinsicObject'


Function IsUNOObject(ByRef rvarObject As Variant) As Boolean

  Dim varDummy As Variant

  On Error Goto ErrorHandler
    'If our object DOES have .Dbg_Properties and .Dbg_Methods then'
    ' it may still be a none-UNO object, if it doesn´t then it '
    ' will fire error 423 if IS a UNO object and error 91 if it is' 
    ' any other type of object'
    'So here´s the belt    '
    varDummy= rvarObject.Dbg_Properties
    'And here´s the braces - less chance of someone else' 
    ' implementing BOTH properties in their own class module than'
    ' just the one!'
    varDummy = rvarObject.Dbg_Methods
    'Add in some superglue!'
    '-If our object is NOT a UNO object this test will fail with'
    ' error 438'
    varDummy = rvarObject.queryInterface(0)
    IsUnoObject = True
  On Error Goto 0

Exit Function 'IsUNOObject'

ErrorHandler: 'Function IsUNOObject'
  
  Select Case Err
    Case 423
      Resume Next
    Case 438
      Resume Next
    Case 91
      IsUNOObject = False
    Case Else
      IsUNOObject = False
  End Select 'Err'

  On Error Goto 0  

End Function 'IsUNOObject'


Function ObjectType(ByRef rvarObject As Variant) As String

  Dim strRet As String
  
  If IsUNOObject(rvarObject) _
  Then
    strRet = "Object-UNO"
  Else 'IsUNOObject(rvobject)'
    On Error Goto ErrorHandler
      strRet = "Object-" & rvarObject.MyClass
    On Error Goto 0
  End If 'IsUNOObject(rvarObject)'
  
  ObjectType = strRet

Exit Function 'ObjectType'

ErrorHandler: 'Function ObjectType'

  On Error Goto 0
  If IsIntrinsicObject(rvarObject) _
  Then
    ObjectType = "Object-Intrinsic"
  Else 'IsIntrinsicObject(rvarObject)'
    ObjectType = "Object-UnknownUserClass"
  End If 'IsIntrinsicObject(rvarObject)'

End Function 'ObjectType'


Function TypeNameEx(ByRef rvarVariable As Variant) As String
  
  Dim lngType As Long
  Dim strRet As String
  
  lngType = VarType(rvarVariable)
  Select Case lngType
    Case 0
      strRet = "Empty"
    Case 1
      strRet = "Null"
    Case 2
      strRet = "Integer"
    Case 3
      strRet = "Long"
    Case 4
      strRet = "Single"
    Case 5
      strRet = "Double"
    Case 6
      strRet = "Currency"
    Case 7
      strRet = "Date"
    Case 8
      strRet = "String"
    Case 9
      strRet = ObjectType(rvarVariable)
    Case Else
      strRet = "Unknown"
  End Select 'lngType'
  
  TypeNameEx = strRet
  
End Function 'TypeNameEx'

There in do distinction between “built-in” UNO objects, and “user” UNO objects. Some “built-ins” are implemented in Python; some are (still) implemented as extensions. An UNO object is just anything that implements a specific UNO interface. Don’t expect that there is some difference.

Thanks Mike - I think I’m going to have to settle for “Object-ClassUnknown” (maybe just “Object”) for any that are built in to LO or haven’t got my .MyClass property.

If I had a comprehensive list of the none-UNO intrinsics and some way to tell whether an object was this type or that (eg a Collection or ErrorObject) then I could just build a monstrously large Select Case statement testing for each in turn.

You can try

Sub Test()
  Dim v
  v = New MyClassModule
  Msgbox HasUnoInterfaces(v, "com.sun.star.uno.XInterface") Or IsUnoStruct(v)
End Sub

For objects that are instances of “ordinary” Basic class modules, False should be returned.

Hi Soko - Thank you for getting back to me. The question is, does the HasUnoInterfaces Or IsUnoStruct get us any further along when trying to distinguish a class module object from a built-in LO Basic class?

I’m being obtuse. Would you, please, give me an example of such a thing?

You may not be being obtuse!

It is my understanding that things like Collections and Arrays (for the sake of just 2 examples) are objects within LO Basic but are not UNO objects, it is that group of objects/classes which I wish to distinguish from user (class module) objects

Start testing with this macro:

Sub ShowObjectType(arg)
  Dim t as String, s as String
  t = TypeName(arg)
  
  If Not IsObject(arg) Then
    s = "is not object"
    
  ElseIf IsUnoStruct(arg) then
    s = "is UNO struct"
 
  ElseIf HasUnoInterfaces(arg, "com.sun.star.uno.XInterface") Then
    s = "is UNO object"
    
  Else
    s = "is other object"
  End If
  
  Msgbox "Parameter (" & t & ") " & s      
End Sub

Sub TestShowObjectType()
  Dim v
  v = new com.sun.star.beans.PropertyValue
  ShowObjectType(v)
  ShowObjectType(ThisComponent)
  v = new Collection
  ShowObjectType(v)
End Sub 

Mmmm - This still doesn’t help me in distinguishing between one of LO Basic’s built in objects and one declared as a user class.
My own code gets us as far as yours does (although your UNO object tell-tales may well be better than the ones which I have employed)

Only one (?) non-UNO object - Collection.

So - ALL LO’s built-in objects/classes are UNO except Collection and (by extension) my IsUNOObject() function will return TRUE for all of them? Have I got that right?

@SVCooper I very much suspect that you and @sokol92 talk past one another, just because you failed to describe what you need, clearly enough. It would be great if you provided a sample pseudocode, like

  type MyType
     ...
  end type

  o1 = new MyType
  o2 = ThisComponent.Sheets(0)
  o3 = ...

  myFunc(o1) ' I want it to produce foo
  myFunc(o2) ' I want it to produce bar
  myFunc(o3) ' I want it to produce baz

I didn’t test your function, but you tested mine, so if you don’t mind, let’s discuss my function. :slight_smile:
I also remembered about the Err object, which can occur when using the Option VBASupport 1 option.
Other objects that are returned by built-in Basic functions are UNO objects (check, maybe something else is not mentioned).

OK, try this

objA = New SomeClassModule (ie one defined in a Class Module)
objB = SomeUNOObjectOrOther (ie any one of ALL the UNO objects)
objC = SomeObjectBuiltIntoLOThatIsntAUNOObject

MyFunc(objA) = “UserClass”
MyFunc(objB) = “UNOClass”
MyFunc(objC) = “IntrinsicLOClass”

My code is likely to already produce the required output for objB (but it may well be refined to make this more likely, I simply don’t know)

I can specify MY OWN class modules to include a .MyClass property so that any object declared as such a (let’s say, “well behaved”), for objA, but I cannot legislate for code written/supplied by AN Other.

I’m struggling to come up with a test that will produce the required output for objC if and only if the object is one of those built into LO which ISN’T a UNO object. By object, by the way, I mean a variable (say V) where VarType(V) = 9.

It may be that:
A - There is no such thing as a built in LO object which ISNT a UNO object, if that is the case then can someone tell me so?
B - There is actually no way in which we can distinguish between a general (ie not my) user object and a built in none UNO LO object, once again, if that is the case then someone please tell me?

I doubt if I can be more clear or concise than that

Your snippet

Else
s = “is other object”
End If

simply tells us that the object is not a UNO object, I’m looking to find out what it is if it ISN’T a UNO object

In LO Basic we have found 2 (two) such objects so far.
If you load application libraries (ScriptForge, …) and those libraries can return objects, you should study how the authors “mark” their objects.

Yes, there are really 3 things which I need to learn in order to achieve my objective:

1 - Just what built-in non UNO objects/classes exist

2 - Having identified what the possible objects and classes are, I have to identify signatures of these OR quite specific things which DON’T apply to them

3 - Finally, how to test for the presence or absence of those signatures

In relation to item 1 we ( myself and @sokol92) have so far identified collections and (I think) error objects. I have tried a little test and failed to declare an error object, so I assume (for the moment at least) that there will only ever be 1 single instance of an error object so that may be moot. I have (elsewhere) had it suggested to me that Scripting.Dictionary may be another but I have so far been unable to test whether or not that is actually a UNO object as my setup throws up errors when I try to declare or assign one (it has been suggested that an option somewhere in LO needs setting but I’m yet to properly investigate). Without trawling through the documentation I can’t be sure but the presence of a period in “Scripting.Dictionary” suggests to me that Scripting is some sort of library so there may well be other objects/classes to explore there. And, of course, you (@sokol92) mention ScriptForge which I also need to investigate.

In relation to item 2, it is one thing to know that a collection (say) is a built-in object but a completely different one knowing HOW to establish that a variable is a collection object, so we need a property or method that only they have or (less accurately) they don’t have.

To some extent items 2 and 3 conflate but, having found a signature, how do we then test for it’s presence? In many cases, I guess, it’s not being present would throw an error if we tried to access or change it…

I should point out that I THINK I have eliminated ALL objects (built in or otherwise) which ARE UNO objects with the first test in my ObjectType function, so any object left to test after that can reasonably be assumed to NOT be UNO

A fun fact:

  x = CreateObject("Scripting.FileSystemObject") ' on Windows '
  MsgBox HasUnoInterfaces(x, "com.sun.star.uno.XInterface") ' -> produces true! '

Of course, internally, the result of creating a COM interface is wrapped into an internal UNO object. But is that relevant for a user, who sees it (and is expected to work with it) not as with UNO object, but as with OLE Automation object?


But what is the actual goal of all these tests? In what sense are these object types different?

1 Like

As I’ve already said, it may be that I simply have to accept that it just isn’t possible to get a finer-grained answer than I already have, ie:

A UNU object
A user object which has a specific property that I test for (eg .MyClass), essentially one of my own
An none UNO object which may either be built-in or written/supplied by AN Other