When I use VBA's VarType
function, passing it an instance of the Object
class available in a mscorlib.dll library reference (a .NET library reference), the value returned is 8
.
According to VBA documentation here, this means the object is a string. This seems ridiculous.
My question is why is the VarType
function returning a string-type value for instances of this Object
class from the .NET-library VBA reference? Is it a bug?
I suspect that the fact that VBA's VarType
function is saying a certain COM object is a string, may be why I'm having problems using the DispCallFunc
function on certain methods of certain COM objects. The COM objects are COM versions of .NET objects, made available through the .NET framework.
I'm using the mscorlib.dll VBA reference to get early-binding functionality for these objects. The reference refers to version 4.0.30319 of the .NET framework. On my computer, the type library for the reference is stored at:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb.
It is looking like when the object method specifies that an argument or return value be of type System.Object
, DispCallFunc
fails to work for me. Anyway, that is a separate problem that is circumstantial to the problem this question is dedicated to.
When I use the VarType
function with instances of other classes from the mscorlib.dll library, I sometimes get return values of 9
& 13
(VbVarType.vbObject
& VbVarType.vbDataObject
constants) which seems correct.
I researched on the internet to see whether anyone else had encountered the problem but couldn't find anything.
Dim o As mscorlib.Object
Set o = New mscorlib.Object
Debug.Print "TypeName(o) = " & TypeName(o) ' TypeName function seems to work correctly.
Debug.Print "o.Equals(o) = " & o.Equals(o) ' System.Object.Equals method is working.
Debug.Print "VarType(CVar(o)) = " & VarType(CVar(o)) ' IMPORTANT LINE
' VBA VarType function says o is string (type 8) but it isn't?!
Debug.Print "VbVarType.vbString = " & VbVarType.vbString
I expected VarType(CVar(o))
to return 9
, 13
or some other appropriate integer. Instead, it returned 8
which does not seem appropriate at all (8
represents strings.)
VarType(varname) The required varname argument is a Variant containing any variable except a variable of a user-defined type.
Excel VBA VarType Function. VBA VARTYPE means “Variable Type.” This function helps us to identify the data type assigned to the specific variable. Simply put, it finds what kind of value is stored or assigned to the variable.
You use the CodeModule object to modify (add, delete, or edit) the code associated with a component. Each component is associated with one CodeModule object.
If you open the typeLib C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb
with OleView for example, and navigate to the _Object
interface (not the first _Object one, the dispinterface, but the second one) you'll see this:
So, the .NET method Object.ToString()
is declared to COM/Automation clients as
[id(00000000), propget, custom(54FC8F55-38DE-4703-9C4E-250351302B1C, 1)]
HRESULT ToString([out, retval] BSTR* pRetVal);
Which means it's seen to COM clients that understand this "syntactic sugar" (VB/VBA/VBScript/JScript/.NET, etc.) as a Property (propget + out + retval) named ToString
that returns a String (BSTR).
Now, id(0)
means it's the default property, because 0 represents DISPID_VALUE, a special well-known id.
And lastly, VB/VBA VarType's documentation states this:
If an object has a default property, VarType(object) returns the type of the object's default property.
(which I always found a pretty strange design decision...)
Looking at the reference source for object.cs
, I'm not seeing any [DispId]
attributes, but assuming the first member gets marshaled with [DispId(0)]
, that would make the ToString
method the COM type's default member.
That's the only explanation I have for Debug.Print o
outputting System.Object
, rather than blowing up with error 438 as it normally would without a default member.
So the problem isn't so much with .NET/COM interop, rather it's about dealing with getting metadata out of an object that has a default member: you would have the exact same problem with any COM object that has a String
default member:
?VarType(Application), VarType(Application.Name)
8 8
I can't think of a way off the top of my head to make VarType
work with these. On the other hand, a TypeOf...Is
check works fine:
?TypeOf Application Is Object
True
Hence:
Debug.Print TypeOf o Is Object ' True
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With