These functions support "pretty printing" for SObs.
Obj_Format()formats a textual representation of an SOb.Obj_Print()also prints that format to the console.Obj_Print0()is a primitive form ofObj_Print(), which prints to the console without formatting.Obj_FormatFields()formats a textual representation of the fields in an SOb, which you supply in a single array. This representation is often used for thedetailsof an SOb.Obj_FormatFields0()is a convenient form ofObj_FormatFields(), where you supply the fields directly.
These functions have the following syntax.
Obj_Format(obj, [depth], [plain], [pointer], [summary], [details], [preview], [orphan], [indent], [break])
Obj_Print(obj, [depth], [plain], [pointer], [summary], [details], [preview], [orphan], [indent], [break])
Obj_Print0([format])
Obj_FormatFields(fields, [separator])
Obj_FormatFields0(…)They have the following named parameters.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
obj |
Collection |
✓ | An SOb you wish to visualize. | |
depth |
Integer |
1 |
The depth to which the visualization should expand: 0 shows a summary, while positive expands to any details. |
|
plain |
Boolean |
False |
Format the SOb in plain format (True) rather than rich (False)? See Examples for appearance. |
|
pointer |
Boolean |
False |
Fall back to showing the pointer (True) for obj, when we have neither summary nor preview? |
|
summary |
String |
"" |
An expression summarizing the contents of obj on a single line, when depth := 0. See preview and pointer for fallbacks when summary := "". |
|
details |
String |
"" |
Expressions detailing the contents of obj across multiple lines, when depth > 0. See Examples for formatting with Obj_FormatFields*(). |
|
preview |
Boolean |
False |
Fall back to showing a preview of the details, when we have no summary? See Examples for appearance. |
|
orphan |
Boolean |
True |
Should a single line of details still be nested (True) or remain on a single line (False)? |
|
indent |
String |
vbTab |
The indentation used for nesting details. Defaults to a standard horizontal tab like most indentation. |
|
break |
String |
vbNewLine |
The linebreak which identifies where lines in details should be indented. See Txt_Indent() for details on usage. |
|
format |
String |
"" |
Output for the console, which should already be formatted as desired. | |
fields |
Array of Strings1 |
✓ | An array with pairs of (textual) expressions: a field name followed by its value. See Examples for appearance. This is best achieved via Array(). |
|
separator |
String |
vbNewLine |
The textual separator displayed between each pairing and the next. Defaults to the system newline, so each pair (.field = value) gets its own line. |
|
| …2 | Strings |
The pairs themselves, entered as individual arguments. This is technically a ParamArray. |
Tip
Use vbNewLine for line breaks, when you assemble (say) details and other such text. This uses the newline specific to the system, and helps Obj_FormatFields*() and Txt_Indent() work frictionlessly.
These functions have the following output.
Obj_Format()returns aStringwith the formatted representation ofobj.Obj_Print()returns the sameStringand also prints it to the console.Obj_Print0()returnsformatand also prints it to the console "as is".Obj_FormatFields()returns aStringwith the formatted representation (.field = value) of all pairs infields.Obj_FormatFields0()does likewise for all pairs in….
Format some field expressions programmatically…
Dim fFormat As String
Dim aFields As Variant: aFields = Array( _
"Bar", "10", _
"Baz", """Twenty""", _
"Qux", "[$A$1:$B$2]" _
)
fFormat = Obj_FormatFields(aFields)
Debug.Print fFormat
Debug.Print
fFormat = Obj_FormatFields(aFields, separator := ", ")
Debug.Print fFormat.Bar = 10 .Baz = "Twenty" .Qux = [$A$1:$B$2] .Bar = 10, .Baz = "Twenty", .Qux = [$A$1:$B$2]
…and manually.
fFormat = Obj_FormatFields0( _
"Bar", "10", _
"Baz", """Twenty""", _
"Qux", "[$A$1:$B$2]" _
)
Debug.Print fFormat.Bar = 10 .Baz = "Twenty" .Qux = [$A$1:$B$2]
Print a "Foo" object in detail…
Dim foo1 As Object: Set foo1 = New_Obj("Foo")
Obj_Print foo1, depth := 1, details := fFormat<Foo: { .Bar = 10 .Baz = "Twenty" .Qux = [$A$1:$B$2] }>
…and in summary.
Obj_Print foo1, depth := 0, summary := "3"<Foo[3]>
In the absence of a summary, default to a preview of any details…
Obj_Print foo1, depth := 0, preview := True
Debug.Print
Obj_Print foo1, depth := 0, preview := True, details := fFormat<Foo: {}> <Foo: {…}>
…or to the pointer…
Obj_Print foo1, depth := 0, pointer := True<Foo @105553139684512>
…or keep it simple.
Obj_Print foo1, depth := 0<Foo>
Format plainly in detail…
Obj_Print foo1, depth := 1, plain := True
Debug.Print
Obj_Print foo1, depth := 1, plain := True, details := fFormat{} { .Bar = 10 .Baz = "Twenty" .Qux = [$A$1:$B$2] }
…and in summary.
Obj_Print foo1, depth := 0, plain := True
Debug.Print
Obj_Print foo1, depth := 0, plain := True, details := fFormat{} {…}
Play with orphan lines…
Obj_Print foo1, depth := 1, details := ".Bar = 10", orphan := False
Debug.Print
Obj_Print foo1, depth := 1, details := ".Bar = 10", orphan := True<Foo: {.Bar = 10}> <Foo: { .Bar = 10 }>
…and indentation.
Obj_Print foo1, depth := 1, details := fFormat, indent := "--> "<Foo: { --> .Bar = 10 --> .Baz = "Twenty" --> .Qux = [$A$1:$B$2] }>
Define a few fields for an SOb of class "Foo"…
Enum Foo__Fields
Bar
Baz
Qux
End Enum…along with their accessors.
Property Get Foo_Bar(foo As Object) As Integer
Obj_Get Foo_Bar, foo, Bar
End Property
Property Let Foo_Bar(foo As Object, val As Integer)
Let Obj_Field(foo, Bar) = val
End Property
Property Get Foo_Baz(foo As Object) As String
Obj_Get Foo_Baz, foo, Baz
End Property
Property Let Foo_Baz(foo As Object, val As String)
Let Obj_Field(foo, Baz) = val
End Property
Property Get Foo_Qux(foo As Object) As Range
Obj_Get Foo_Qux, foo, Qux
End Property
Property Set Foo_Qux(foo As Object, val As Range)
Set Obj_Field(foo, Qux) = val
End PropertyDefine3 simple Foo_Format() and Foo_Print() methods for "Foo".
Function Foo_Format(foo As Object, _
depth As Integer, _
plain As Boolean _
) As String
Dim sSummary As String: sSummary = VBA.CStr(Obj_FieldCount(foo))
Dim sDetails As String: sDetails = Obj_FormatFields0( _
"Bar", VBA.CStr(Foo_Bar(foo)), _
"Baz", """" & Foo_Baz(foo) & """", _
"Qux", "[" & Foo_Qux(foo).Address & "]" _
)
Foo_Format = Obj_Format(foo, _
summary := sSummary, _
details := sDetails, _
depth := depth, _
plain := plain, _
orphan := False, _
indent := vbTab _
)
End Function
Function Foo_Print(foo As Object, _
Optional depth As Integer = 1, _
Optional plain As Boolean = False _
) As String
Foo_Print = Foo_Format(foo, depth := depth, plain := plain)
Obj_Print0 Foo_Print
End FunctionPrint a "Foo" object4 richly…
Foo_Bar(foo1) = -1
Foo_Baz(foo1) = "text"
Set Foo_Qux(foo1) = [C3:D4]
Foo_Print foo1, depth := 0
Debug.Print
Foo_Print foo1, depth := 1<Foo[3]> <Foo: { .Bar = -1 .Baz = "text" .Qux = [$C$3:$D$4] }>
…and plainly.
Foo_Print foo1, depth := 0, plain := True
Debug.Print
Foo_Print foo1, depth := 1, plain := True{…} { .Bar = -1 .Baz = "text" .Qux = [$C$3:$D$4] }
Define a few fields for an SOb of class "Snaf"…
Enum Snaf__Fields
TxtField
FooField
End Enum…along with their accessors.
Property Get Snaf_TxtField(snaf As Object) As String
Obj_Get Snaf_TxtField, snaf, TxtField
End Property
Property Let Snaf_TxtField(snaf As Object, val As String)
Let Obj_Field(snaf, TxtField) = val
End Property
Property Get Snaf_FooField(snaf As Object) As Object
Obj_Get Snaf_FooField, snaf, FooField
End Property
Property Set Snaf_FooField(snaf As Object, val As Object)
Set Obj_Field(snaf, FooField) = val
End PropertyDefine a simple Snaf_Print() method for "Snaf", which decrements depth and passes it (and plain) recursively to the Foo_Print() method for its FooField field.
Function Snaf_Print(snaf As Object, _
Optional depth As Integer = 1, _
Optional plain As Boolean = False _
) As String
Dim sSummary As String: sSummary = "Situation normal"
Dim sDetails As String: sDetails = Obj_FormatFields0( _
"TxtField", """" & Snaf_TxtField(snaf) & """", _
"FooField", Foo_Format(Snaf_FooField(snaf), depth := depth - 1, plain := plain) _
)
Snaf_Print = Obj_Format(snaf, _
summary := sSummary, _
details := sDetails, _
depth := depth, _
plain := plain, _
orphan := False, _
indent := vbTab _
)
Obj_Print0 Snaf_Print
End FunctionPrint a "Snaf" object to various depths, in rich format…
Dim snaf1 As Object: Set snaf1 = New_Obj("Snaf")
Snaf_TxtField(snaf1) = "some more text"
Set Snaf_FooField(snaf1) = foo1
Snaf_Print snaf1, depth := 0
Debug.Print
Snaf_Print snaf1, depth := 1
Debug.Print
Snaf_Print snaf1, depth := 2<Snaf[Situation normal]> <Snaf: { .TxtField = "some more text" .FooField = <Foo[3]> }> <Snaf: { .TxtField = "some more text" .FooField = <Foo: { .Bar = -1 .Baz = "text" .Qux = [$C$3:$D$4] }> }>
…and in plain format.
Snaf_Print snaf1, depth := 0, plain := True
Debug.Print
Snaf_Print snaf1, depth := 1, plain := True
Debug.Print
Snaf_Print snaf1, depth := 2, plain := True{…} { .TxtField = "some more text" .FooField = {…} } { .TxtField = "some more text" .FooField = { .Bar = -1 .Baz = "text" .Qux = [$C$3:$D$4] } }
Topics in this project…
*0()family- Fields
Txt_Indent()- Templates
- Setup with templates
- Enumerated fields
- Field accessors
- Formatting
- Printing
…in VBA…
.Print()method- Immediate window in the Visual Basic Editor (VBE)
- Arrays
Collections- Pointers
vbTabArray()vbNewLineParamArrays- Named arguments
EnumerationsCStr()Ranges.Addressproperty- Shortcut notation
…and elsewhere.
Footnotes
-
You may use a
String()array, or aVariant()array containingStrings. ↩ -
ParamArrays like…are not actually passed to a single named argument, but rather as several nameless arguments. ↩ -
Use
CStr()to convert various values into textualStrings. ↩ -
You may specify a
Rangewith its.Addressin shortcut notation:[A1:B2]. ↩