Skip to content

Latest commit

 

History

History
603 lines (448 loc) · 16.9 KB

File metadata and controls

603 lines (448 loc) · 16.9 KB

Visualization

Description

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 of Obj_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 the details of an SOb.
  • Obj_FormatFields0() is a convenient form of Obj_FormatFields(), where you supply the fields directly.

Syntax

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.

Output

These functions have the following output.

  • Obj_Format() returns a String with the formatted representation of obj.
  • Obj_Print() returns the same String and also prints it to the console.
  • Obj_Print0() returns format and also prints it to the console "as is".
  • Obj_FormatFields() returns a String with the formatted representation (.field = value) of all pairs in fields.
  • Obj_FormatFields0() does likewise for all pairs in .

Examples

Field Formatting

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]

Printing Objects

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]>

Summarizing Objects

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>

Plain Formatting

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
{}

{…}

Miscellaneous Settings

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]
}>

Implement Printing

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 Property

Define3 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 Function

Print 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]
}

Nested Printing

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 Property

Define 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 Function

Print 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]
	}
}

See Also

Topics in this project…

…in VBA…

…and elsewhere.

Footnotes

  1. You may use a String() array, or a Variant() array containing Strings.

  2. ParamArrays like are not actually passed to a single named argument, but rather as several nameless arguments.

  3. Use CStr() to convert various values into textual Strings.

  4. You may specify a Range with its .Address in shortcut notation: [A1:B2].