patternMinor
Representing Objects as strings in VBA
Viewed 0 times
objectsstringsrepresentingvba
Problem
I am working an a more meaningful way to print objects in VBA. The desired result should look something like this.
The concept is that objects implementing an
And other objects are represented as "TypeName(&ObjPtr)"
But the issue that is gunking up my design is that I want nested objects to represent themselves
My solution is to use an auxiliary helper methods, located in a standard module called
I would want this to be located in the
Now any method that is printing the objects can just u
Console.PrintLine List.Create(1, 2, 3)
List(1, 2, 3)The concept is that objects implementing an
IPrintable interface are printed as their ToString property. Primitive data types are printed as isConsole.PrintLine "a"
aAnd other objects are represented as "TypeName(&ObjPtr)"
Console.PrintLine New Collection
Collection(&150653720)But the issue that is gunking up my design is that I want nested objects to represent themselves
Console.PrintLine List.Create(1, List.Create(), New Collection)
List(1, List(), Collection(&150653384))My solution is to use an auxiliary helper methods, located in a standard module called
cast, which in a way provides a default implementation of IPrintablePublic Function ToString(ByVal x As Variant) As String
Dim result As String
If TypeOf x Is IPrintable Then
result = x.ToString
ElseIf IsObject(x) Then
result = DefaultObjectToString(x)
Else
result = CStr(x)
End If
ToString = result
End Function
Private Function DefaultObjectToString(ByVal x As Object) As String
DefaultObjectToString = ObjectToString(x, cast.CArray(Array("&" & ObjPtr(x))))
End Function
Public Function ObjectToString(ByVal o As Object, ByRef members() As Variant, _
Optional ByVal delim As String = ", ") As String
Dim stringMembers() As String
If LBound(members) <= UBound(members) Then
ReDim stringMembers(LBound(members) To UBound(members))
End If
Dim i As Long
For i = LBound(members) To UBound(members)
stringMembers(i) = ToString(members(i))
Next i
ObjectToString = TypeName(o) & "(" & Join(stringMembers, delim) & ")"
End FunctionI would want this to be located in the
IPrintable class but that must be empty to use it as an interface.Now any method that is printing the objects can just u
Solution
I don't see anything ugly about your
What I do question is the usefulness of defaulting to the object's pointer as a string representation of it. Since VB6 supports default properties, I would take advantage of it. It's not exactly pretty, but perhaps a more useful representation of an object.
Which would change this function:
Into this:
This provides a much nicer string back. Consider a workbook with a value of "Hello!" in cell A1 and the following code.
This would result in the following:
Cast module. If it was .Net I would use a Static (Shared) type class, and a standard *.bas module is roughly equivalent in VB6. It seems to have been the right move to me. What I do question is the usefulness of defaulting to the object's pointer as a string representation of it. Since VB6 supports default properties, I would take advantage of it. It's not exactly pretty, but perhaps a more useful representation of an object.
Private Function TryCastToString(x As Variant) As String
On Error GoTo ErrHandler
TryCastToString = CStr(x)
Exit Function
ErrHandler:
Const MethodNotSupportedError As Integer = 438
If Err.Number = MethodNotSupportedError Then
TryCastToString = "&" & ObjPtr(x)
Else
Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext
End If
End FunctionWhich would change this function:
Private Function DefaultObjectToString(ByVal x As Object) As String
DefaultObjectToString = ObjectToString(x, cast.CArray(Array("&" & ObjPtr(x))))
End FunctionInto this:
Private Function DefaultObjectToString(ByVal x As Object) As String
DefaultObjectToString = ObjectToString(x, cast.CArray(Array(TryCastToString(x))))
End FunctionThis provides a much nicer string back. Consider a workbook with a value of "Hello!" in cell A1 and the following code.
Public Sub test()
Debug.Print Cast.ToString(ThisWorkbook)
Debug.Print Cast.ToString(Range("A1"))
End SubThis would result in the following:
Workbook(&2349672)
Range(Hello!)Code Snippets
Private Function TryCastToString(x As Variant) As String
On Error GoTo ErrHandler
TryCastToString = CStr(x)
Exit Function
ErrHandler:
Const MethodNotSupportedError As Integer = 438
If Err.Number = MethodNotSupportedError Then
TryCastToString = "&" & ObjPtr(x)
Else
Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext
End If
End FunctionPrivate Function DefaultObjectToString(ByVal x As Object) As String
DefaultObjectToString = ObjectToString(x, cast.CArray(Array("&" & ObjPtr(x))))
End FunctionPrivate Function DefaultObjectToString(ByVal x As Object) As String
DefaultObjectToString = ObjectToString(x, cast.CArray(Array(TryCastToString(x))))
End FunctionPublic Sub test()
Debug.Print Cast.ToString(ThisWorkbook)
Debug.Print Cast.ToString(Range("A1"))
End SubWorkbook(&2349672)
Range(Hello!)Context
StackExchange Code Review Q#78797, answer score: 5
Revisions (0)
No revisions yet.