Why would you want to?
Getting started with encoding data
Creating JSON from Excel data
Creating an Adhoc hierarchical object framework
' In thisworkbook Private Sub Workbook_BeforeClose(Cancel As Boolean) wbCloseShapeVersion End Sub Private Sub Workbook_Open() wbOpenShapeVersion End Sub
Sub wbOpenShapeVersion() 'workbook has opened With Sheets(hiddenShapeSheet).Shapes(hiddenShape) .AlternativeText = _ openingData(CStr(.AlternativeText)).Serialize End With End Sub
Sub wbCloseShapeVersion() 'workbook is closing With Sheets(hiddenShapeSheet).Shapes(hiddenShape) .AlternativeText = _ closingData(CStr(.AlternativeText)).Serialize End With End Sub
Private Function openingData(s As String) As cJobject ' create serialization object Dim cj As cJobject Set cj = New cJobject Set cj = cj.deSerialize(s) If cj.key <> cKeyName Or Not cj.Valid Then Set cj = New cJobject cj.init Nothing, cKeyName End If ' setup the data relevant to opening With cj.Add("lastaccess") .Add ("username"), Environ("USERNAME") .Add ("startedat"), Now End With ' will need these later so add them in case they dontr exist already With cj.Add("summary") .Add ("timeopen") .Add ("countopen") End With Set openingData = cj End Function
Private Function closingData(s As String) As cJobject ' create serialization object Dim cj As cJobject Set cj = New cJobject Set cj = cj.deSerialize(s) If cj.key <> cKeyName Or Not cj.Valid Then Set cj = New cJobject cj.init Nothing, cKeyName End If ' setup the data relevant to closing With cj.Add("lastaccess") .Add ("finishedat"), Now End With If cj.isValid Then With cj.Add("summary") .Add ("timeopen"), .Child("timeopen").asLong _ + DateDiff("s", cj.Child("lastaccess.startedat").value, Now()) .Add ("countopen"), .Child("countopen").asLong + 1 End With End If Set closingData = cj End Function
Some note on cJobject class
{"hiddendata": {"lastaccess": {"username": "fhk647","startedat": "1/31/2011 4:47:29 PM","finishedat": "1/31/2011 4:24:57 PM"},"summary": {"timeopen": "10772","countopen": "3"}}}
Public Property Get isValid() As Boolean Public Property Get Parent() As cJobject Public Property Get Root() As cJobject Public Property Get Key() As String Public Property Get Value() As Variant Public Property Get Children() As Collection Public Property Get hasChildren() As Boolean Public Property Get asLong() As Long Public Property Get asDate() As Date Public Property Get asString() As String Public Property Get asDouble() As Double Public Property Get asBoolean() As Boolean Public Sub init(p As cJobject, Optional k As String = "_null", Optional v As Variant = Empty) Public Function Child(s As String) As cJobject Public Function Add(k As String, Optional v As Variant = Empty) As cJobject Public Function ChildExists(s As String) As cJobject Public Function fullKey() As String Public Function Serialize() As String Public Property Get formatData() As String Public Function deSerialize(s As String) As cJobject Private Function dsProcess(job As cJobject, Optional whatNext As String = "{") As cJobject
This is a class that looks like this. (by the way, I’m using a Google Visualization to display an orgchart view of the object below – see section on Google Visualization on this site
It is possible to refer to the properties of these items in a number of ways, for example
cj.child("summary).child("countopen").value cj.child("summary.countopen").value
both refer to the same thing.
Serialization and De-serialization
cj.deserialize(str)
takes the JSON string str, and returns the root of a hierarchy of cJobject containing that data. If cj already had children when the deserialize method was called then the new heirachy represented by str will become a child of cj.
cj.serialize(str)
takes the heirachy of cJobects represented by cj, and returned a serialized JSON string. Although this string is standard, valid JSON, arrays are not implented and all values are converted to strings. This is not an issue for the use case in this section, but may be if you wanted to use the class in a different context.
cj.deserialize(str).serialize
then, should simply return a string equivalent to str.
Recursion and cJobject
Public Function Serialize() As String ' make a JSON string of this structure Serialize = "{" & recurseSerialize(Me) & "}" End Function
Public Function recurseSerialize(job As cJobject, Optional soFar As String = "") As String Dim s As String, jo As cJobject s = soFar & quote(job.Key) & ": " If Not job.hasChildren Then s = s & quote(CStr(job.Value)) Else s = s & "{" For Each jo In job.Children s = recurseSerialize(jo, s) & "," Next jo s = Left(s, Len(s) - 1) & "}" End If recurseSerialize = s End Function
Embedding in other objects
'Using a cell Sub OpenCellVersion(sr As String) With Range(sr) .Value = openingData(CStr(.Value)).Serialize End With End Sub 'using a shape Sub wbOpenShapeVersion() 'workbook has opened With Sheets(hiddenShapeSheet).Shapes(hiddenShape) .AlternativeText = openingData(CStr(.AlternativeText)).Serialize End With End Sub
In the downloadable example I have implemented a workbook tracker in both a cell and shape, as well as form tracker which collects statistics about the usage of a particular form.