Answering my own question here. It is possible to call into JavaScript running in the Microsoft Script Control and return some JSON data structure. Whilst it is possible to parse the JSON with the Evaluate method of the script control, sometimes one wants to write to a two dimensional (2d) variant array which can then be pasted directly to a sheet or return in a user defined function. This bumps up against marshalling of data structures.
One cannot pass a 2d variant array into a JavaScript function, write to it and then pass it back. [If you have proof that is untrue please post]. So this code fails
'Tools->References->
'Microsoft Script Control 1.0; {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}; C:\Windows\SysWOW64\msscript.ocx
Private Sub TestJSONtoOleVariantGridFails1()
Dim oScriptEngine As ScriptControl
Set oScriptEngine = New ScriptControl
oScriptEngine.Language = "JScript"
oScriptEngine.AddCode "function WriteResults1(vGrid) { vGrid(0,0)=1.2;vGrid(0,1)='red';vGrid(1,0)=true;vGrid(1,1)=null; return vGrid;};"
ReDim vGridBefore(0 To 1, 0 To 1)
Dim vGridAfter
vGridAfter = oScriptEngine.Run("WriteResults1", vGridBefore) '<---- FAILS with error "Cannot assign to a function result"
Debug.Assert vGridAfter(0, 0) = 1.2
Debug.Assert vGridAfter(0, 1) = "red"
Debug.Assert vGridAfter(1, 0) = True
Debug.Assert IsNull(vGridAfter(1, 1))
End Sub
So this begs the question how best to populate a 2d variant array?
I have a solution which I'm posting but I'd be fascinated to know if someone else has figured out the marshalling between JSON and 2d variant arrays.
Here is my solution which works by creating a class to wrap the 2d variant array and then passing in a reference to the class. This is like "boxing".
'Tools->References->
'Microsoft Script Control 1.0; {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}; C:\Windows\SysWOW64\msscript.ocx
Private Sub TestJSONtoOleVariantGridSucceeds()
Dim oScriptEngine As ScriptControl
Set oScriptEngine = New ScriptControl
oScriptEngine.Language = "JScript"
oScriptEngine.AddCode "function WriteResults(oGrid) { oGrid.Redimension(2,2); oGrid.Cell(0,0)=1.2;oGrid.Cell(0,1)='red';oGrid.Cell(1,0)=true;oGrid.Cell(1,1)=null;};"
Dim oGrid As JSONOLEVariant
Set oGrid = New JSONOLEVariant
Call oScriptEngine.Run("WriteResults", oGrid)
Dim vGrid As Variant
vGrid = oGrid.ExportGridData
Debug.Assert vGrid(0, 0) = 1.2
Debug.Assert vGrid(0, 1) = "red"
Debug.Assert vGrid(1, 0) = True
Debug.Assert IsNull(vGrid(1, 1))
End Sub
and the class code JSONOLEVariant.cls
Option Explicit
Option Base 0
Private mvGridData As Variant
Public Function ExportGridData()
ExportGridData = mvGridData
End Function
Public Sub Redimension(ByVal lRows As Long, ByVal lColumns As Long)
ReDim mvGridData(0 To lRows - 1, 0 To lColumns - 1) 'Zero base
End Sub
Public Property Let Cell(ByVal lRow As Long, ByVal lColumn As Long, ByVal vNewValue As Variant)
mvGridData(lRow, lColumn) = vNewValue
End Property
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.