web-dev-qa-db-fra.com

Existe-t-il un analyseur JSON pour VB6/VBA?

J'essaie de consommer un service Web dans VB6. Le service - que je contrôle - peut actuellement renvoyer un message SOAP/XML ou JSON. J'ai beaucoup de difficulté à déterminer si le type SOAP de VB6 (version 1) peut gérer une valeur retournée object - par opposition aux types simples tels que string, int, etc. pour que VB6 joue avec les objets retournés.

J'ai donc pensé pouvoir sérialiser la réponse dans le service Web en tant que chaîne JSON. Un analyseur JSON existe-t-il pour VB6?

37
Ben McCormack

Consultez JSON.org pour une liste à jour (voir au bas de la page principale) d’analyseurs JSON dans de nombreuses langues. Au moment d'écrire ces lignes, vous verrez un lien vers deux analyseurs JSON différents:

  • VB-JSON

    • Lorsque j'ai essayé de télécharger le fichier Zip, Windows a déclaré que les données étaient corrompues. Cependant, j'ai pu utiliser 7-Zip pour extraire les fichiers. Il s'avère que le "dossier" principal du fichier Zip n'est pas reconnu comme un dossier par Windows. Par 7-Zip, il peut voir le contenu de ce "dossier" principal. Vous pouvez donc l'ouvrir et extraire les fichiers en conséquence .
    • La syntaxe réelle de cette bibliothèque JSON VB est très simple:

      Dim p As Object
      Set p = JSON.parse(strFormattedJSON)
      
      'Print the text of a nested property '
      Debug.Print p.Item("AddressClassification").Item("Description")
      
      'Print the text of a property within an array '
      Debug.Print p.Item("Candidates")(4).Item("ZipCode")
      
    • Remarque: j'ai dû ajouter les bibliothèques "Microsoft Scripting Runtime" et "Microsoft ActiveX Data Objects 2.8" comme références via Outils> Références dans l'éditeur VBA.
    • Remarque: le code VBJSON est basé sur un projet de code Google vba-json . Cependant, VBJSON promet plusieurs corrections de bugs de la version originale.
  • PW.JSON
    • C'est en fait une bibliothèque pour VB.NET, je n'ai donc pas passé beaucoup de temps à la regarder.
39
Ben McCormack

S'appuyant sur la solution ozmike, qui ne fonctionnait pas pour moi (Excel 2013 et IE10) . La raison en est que je ne pouvais pas appeler les méthodes sur l'objet JSON exposé . Ses méthodes sont maintenant exposées au travers de fonctions attachées à un DOMElement . Je ne savais pas que c'était possible (ce doit être cette chose-IDispatch), merci Ozmike.

Comme Ozmike l'a déclaré, pas de bibliothèque tierce partie, seulement 30 lignes de code.

Option Explicit

Public JSON As Object
Private ie As Object

Public Sub initJson()
    Dim html As String

    html = "<!DOCTYPE html><head><script>" & _
    "Object.prototype.getItem=function( key ) { return this[key] }; " & _
    "Object.prototype.setItem=function( key, value ) { this[key]=value }; " & _
    "Object.prototype.getKeys=function( dummy ) { keys=[]; for (var key in this) if (typeof(this[key]) !== 'function') keys.Push(key); return keys; }; " & _
    "window.onload = function() { " & _
    "document.body.parse = function(json) { return JSON.parse(json); }; " & _
    "document.body.stringify = function(obj, space) { return JSON.stringify(obj, null, space); }" & _
    "}" & _
    "</script></head><html><body id='JSONElem'></body></html>"

    Set ie = CreateObject("InternetExplorer.Application")
    With ie
        .navigate "about:blank"
        Do While .Busy: DoEvents: Loop
        Do While .readyState <> 4: DoEvents: Loop
        .Visible = False
        .document.Write html
        .document.Close
    End With

    ' This is the body element, we call it JSON:)
    Set JSON = ie.document.getElementById("JSONElem")

End Sub

Public Function closeJSON()
    ie.Quit
End Function

Le test suivant construit un objet JavaScript à partir de rien, puis le hiérarchise . Il analyse ensuite l'objet et effectue une itération sur ses clés.

Sub testJson()
    Call initJson

    Dim jsObj As Object
    Dim jsArray As Object

    Debug.Print "Construction JS object ..."
    Set jsObj = JSON.Parse("{}")
    Call jsObj.setItem("a", 1)
    Set jsArray = JSON.Parse("[]")
    Call jsArray.setItem(0, 13)
    Call jsArray.setItem(1, Math.Sqr(2))
    Call jsArray.setItem(2, 15)
    Call jsObj.setItem("b", jsArray)

    Debug.Print "Object: " & JSON.stringify(jsObj, 4)

    Debug.Print "Parsing JS object ..."
    Set jsObj = JSON.Parse("{""a"":1,""b"":[13,1.4142135623730951,15]}")

    Debug.Print "a: " & jsObj.getItem("a")
    Set jsArray = jsObj.getItem("b")
    Debug.Print "Length of b: " & jsArray.getItem("length")
    Debug.Print "Second element of b: "; jsArray.getItem(1)

    Debug.Print "Iterate over all keys ..."
    Dim keys As Object
    Set keys = jsObj.getKeys("all")

    Dim i As Integer
    For i = 0 To keys.getItem("length") - 1
        Debug.Print keys.getItem(i) & ": " & jsObj.getItem(keys.getItem(i))
    Next i

    Call closeJSON
End Sub

les sorties

Construction JS object ...
Object: {
    "a": 1,
    "b": [
        13,
        1.4142135623730951,
        15
    ]
}
Parsing JS object ...
a: 1
Length of b: 3
Second element of b:  1,4142135623731 
Iterate over all keys ...
a: 1
b: 13,1.4142135623730951,15
14
Wolfgang Kuehn

Je sais que c’est une vieille question, mais ma réponse sera d’une grande aide pour ceux qui continuent à consulter cette page après avoir recherché "vba json". 

J'ai trouvé cette page très utile. Il fournit plusieurs classes VBA compatibles Excel qui traitent du traitement des données au format JSON.

7
dashmug

MISE À JOUR: trouvé un moyen plus sûr d'analyser JSON que d'utiliser Eval, ce billet de blog montre les dangers d'Eval ... http://exceldevelopmentplatform.blogspot.com/2018/01/vba-parse-json-safer- avec-jsonparse-and.html

En retard pour cette soirée, mais désolé les gars, mais de loin le moyen le plus simple consiste à utiliser Microsoft Script Control. Un exemple de code utilisant VBA.CallByName pour accéder au détail

'Tools->References->
'Microsoft Script Control 1.0;  {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}; C:\Windows\SysWOW64\msscript.ocx

Private Sub TestJSONParsingWithCallByName()

    Dim oScriptEngine As ScriptControl
    Set oScriptEngine = New ScriptControl
    oScriptEngine.Language = "JScript"

    Dim sJsonString As String
    sJsonString = "{'key1': 'value1'  ,'key2': { 'key3': 'value3' } }"


    Dim objJSON As Object
    Set objJSON = oScriptEngine.Eval("(" + sJsonString + ")")
    Debug.Assert VBA.CallByName(objJSON, "key1", VbGet) = "value1"
    Debug.Assert VBA.CallByName(VBA.CallByName(objJSON, "key2", VbGet), "key3", VbGet) = "value3"

End Sub

J'ai en fait préparé une série de questions et réponses sur des sujets liés à JSON/VBA.

Q1 Dans Excel VBA sous Windows, comment atténuer le problème de traversée de la syntaxe à points du JSON analysé, brisé par le comportement de capitalisation de l'EDI?

Q2 Dans Excel VBA sous Windows, comment parcourir une matrice JSON analysée?

Q3 Dans Excel VBA sous Windows, comment obtenir une représentation JSON sous forme de chaîne au lieu de «[objet Objet]» pour les variables JSON analysées?

Q4 Dans Windows Excel VBA, comment obtenir des clés JSON pour éviter l’erreur «Erreur d’exécution '438': l’objet ne prend pas en charge cette propriété ou cette méthode»?

Q5 Dans Excel VBA sous Windows, pour les variables JSON analysées, qu’est-ce que JScriptTypeInfo de toute façon?

5
S Meaden

Voici une bibliothèque JSON "native" VB.

Il est possible d'utiliser JSON déjà présent dans IE8 +. De cette façon, vous n'êtes pas dépendant d'une bibliothèque tierce périmée et non testée.

voir la version alternative de amedeus ici

Sub myJSONtest()


Dim oJson As Object
Set oJson = oIE_JSON() ' See below gets IE.JSON object

' using json objects
Debug.Print oJson.parse("{ ""hello"": ""world"" }").hello ' world
Debug.Print oJson.stringify(oJson.parse("{ ""hello"": ""world"" }")) ' {"hello":"world"}

' getting items
Debug.Print oJson.parse("{ ""key1"": ""value1"" }").key1 ' value1
Debug.Print oJson.parse("{ ""key1"": ""value1"" }").itemGet("key1") ' value1
Debug.Print oJson.parse("[ 1234, 4567]").itemGet(1) '  4567

' change  properties
Dim o As Object
Set o = oJson.parse("{ ""key1"": ""value1"" }")
o.propSetStr "key1", "value\""2"
Debug.Print o.itemGet("key1") ' value\"2
Debug.Print oJson.stringify(o) ' {"key1":"value\\\"2"}
o.propSetNum "key1", 123
Debug.Print o.itemGet("key1") ' 123
Debug.Print oJson.stringify(o) ' {"key1":123}

' add properties
o.propSetNum "newkey", 123 ' addkey! JS MAGIC
Debug.Print o.itemGet("newkey") ' 123
Debug.Print oJson.stringify(o) ' {"key1":123,"newkey":123}

' assign JSON 'objects' to properties
Dim o2 As Object
Set o2 = oJson.parse("{ ""object2"": ""object2value"" }")
o.propSetJSON "newkey", oJson.stringify(o2) ' set object
Debug.Print oJson.stringify(o) ' {"key1":123,"newkey":{"object2":"object2value"}}
Debug.Print o.itemGet("newkey").itemGet("object2") ' object2value

' change array items
Set o = oJson.parse("[ 1234, 4567]") '
Debug.Print oJson.stringify(o) ' [1234,4567]
Debug.Print o.itemGet(1)
o.itemSetStr 1, "234"
Debug.Print o.itemGet(1)
Debug.Print oJson.stringify(o) ' [1234,"234"]
o.itemSetNum 1, 234
Debug.Print o.itemGet(1)
Debug.Print oJson.stringify(o) ' [1234,234]

' add array items
o.itemSetNum 5, 234 ' add items! JS Magic
Debug.Print o.itemGet(5) ' 234
Debug.Print oJson.stringify(o) ' [1234,234,null,null,null,234]

' assign JSON object to array item
o.itemSetJSON 3, oJson.stringify(o2)  ' assign object
Debug.Print o.itemGet(3) '[object Object]
Debug.Print oJson.stringify(o.itemGet(3)) ' {"object2":"object2value"}
Debug.Print oJson.stringify(o) ' [1234,234,null,{"object2":"object2value"},null,234]


oIE_JSON_Quit ' quit IE, must shut down or the IE sessions remain.
Debug.Print oJson.stringify(o) ' can use after but but IE server will shutdown... soon
End Sub

Vous pouvez créer un lien vers IE.JSON à partir de VB.
Créer une fonction oIE_JSON

Public g_IE As Object ' global


Public Function oIE_JSON() As Object


    ' for array access o.itemGet(0) o.itemGet("key1")
    JSON_COM_extentions = "" & _
            " Object.prototype.itemGet        =function( i ) { return this[i] }   ;            " & _
            " Object.prototype.propSetStr     =function( prop , val ) { eval('this.' + prop + '  = ""' + protectDoubleQuotes (val) + '""' )   }    ;            " & _
            " Object.prototype.propSetNum     =function( prop , val ) { eval('this.' + prop + '  = ' + val + '')   }    ;            " & _
            " Object.prototype.propSetJSON    =function( prop , val ) { eval('this.' + prop + '  = ' + val + '')   }    ;            " & _
            " Object.prototype.itemSetStr     =function( prop , val ) { eval('this[' + prop + '] = ""' + protectDoubleQuotes (val) + '""' )   }    ;            " & _
            " Object.prototype.itemSetNum     =function( prop , val ) { eval('this[' + prop + '] = ' + val )   }    ;            " & _
            " Object.prototype.itemSetJSON    =function( prop , val ) { eval('this[' + prop + '] = ' + val )   }    ;            " & _
            " function protectDoubleQuotes (str)   { return str.replace(/\\/g, '\\\\').replace(/""/g,'\\""');   }"

    ' document.parentwindow.eval dosen't work some versions of ie eg ie10?
     IEEvalworkaroundjs = "" & _
         " function IEEvalWorkAroundInit ()   { " & _
         " var x=document.getElementById(""myIEEvalWorkAround"");" & _
         " x.IEEval= function( s ) { return eval(s) } ; } ;"

    g_JS_framework = "" & _
      JSON_COM_extentions & _
      IEEvalworkaroundjs

    ' need IE8 and DOC type
    g_JS_HTML = "<!DOCTYPE html>  " & _
         " <script>" & g_JS_framework & _
                  "</script>" & _
         " <body>" & _
         "<script  id=""myIEEvalWorkAround""  onclick=""IEEvalWorkAroundInit()""  ></script> " & _
                 " HEllo</body>"

On Error GoTo error_handler

' Create InternetExplorer Object
Set g_IE = CreateObject("InternetExplorer.Application")
With g_IE
    .navigate "about:blank"
    Do While .Busy: DoEvents: Loop
    Do While .ReadyState <> 4: DoEvents: Loop
    .Visible = False ' control IE interface window
    .Document.Write g_JS_HTML
End With

Set objID = g_IE.Document.getElementById("myIEEvalWorkAround")
objID.Click ' create  eval
Dim oJson As Object

'Set oJson = g_IE.Document.parentWindow.Eval("JSON") ' dosen't work some versions of IE
Set oJson = objID.IEEval("JSON")

Set objID = Nothing
Set oIE_JSON = oJson

Exit Function
error_handler:
MsgBox ("Unexpected Error, I'm quitting. " & Err.Description & ".  " & Err.Number)
g_IE.Quit
Set g_IE = Nothing

End Function

Public Function oIE_JSON_Quit()
         g_IE.Quit
         Exit Function
End Function

Votez si vous trouvez utile

4
ozmike

VBA-JSON de Tim Hall, MIT sous licence et sur GitHub. C'est une autre fourchette de vba-json qui est apparue à la fin de 2014. Elle prétend fonctionner sur Mac Office et Windows 32 bits et 64 bits.

4
Patrick Böker

VB6 - JsonBag, un autre analyseur/générateur JSON devrait également pouvoir être importé dans VBA avec peu de problèmes.

3
Bob77

Vous pouvez écrire un complément Excel-DNA dans VB.NET. Excel-DNA est une bibliothèque mince qui vous permet d'écrire des fichiers XLL dans .NET. De cette façon, vous avez accès à l’ensemble de l’univers .NET et pouvez utiliser des éléments tels que http://james.newtonking.com/json - un framework JSON qui désérialise JSON dans n’importe quelle classe personnalisée.

Si cela vous intéresse, voici une description de la création d'un client JSON Excel générique pour Excel à l'aide de VB.NET:

http://optionexplicitvba.com/2014/05/09/developing-a-json-Excel-add-in-with-vb-net/

Et voici le lien vers le code: https://github.com/spreadgit/Excel-json-client/blob/master/Excel-json-client.dna

2
Bjoern Stiel

Je suggère d'utiliser un composant .Net. Vous pouvez utiliser des composants .Net à partir de VB6 via Interop - voici un tutorial . Mon hypothèse est que les composants .Net seront plus fiables et mieux pris en charge que tout ce qui est produit pour VB6. 

Il existe des composants dans le framework Microsoft .Net tels que DataContractJsonSerializer ou JavaScriptSerializer . Vous pouvez également utiliser des bibliothèques tierces telles que JSON.NET

2
MarkJ

Comme Json n’est que des chaînes, il est facile à manipuler si nous pouvons le manipuler correctement, quelle que soit la complexité de la structure. Je ne pense pas qu'il soit nécessaire d'utiliser une bibliothèque externe ou un convertisseur pour faire l'affaire. Voici un exemple où j'ai analysé des données JSON à l'aide d'une manipulation de chaîne.

Sub GetJsonContent()
    Dim http As New XMLHTTP60, itm As Variant

    With http
        .Open "GET", "http://jsonplaceholder.typicode.com/users", False
        .send
        itm = Split(.responseText, "id"":")
    End With

    x = UBound(itm)

    For y = 1 To x
        Cells(y, 1) = Split(Split(itm(y), "name"": """)(1), """")(0)
        Cells(y, 2) = Split(Split(itm(y), "username"": """)(1), """")(0)
        Cells(y, 3) = Split(Split(itm(y), "email"": """)(1), """")(0)
        Cells(y, 4) = Split(Split(itm(y), "street"": """)(1), """")(0)
    Next y
End Sub
0
SIM

Formule dans une cellule Excel

=JSON2("{mykey:1111, mykey2:{keyinternal1:22.1,keyinternal2:22.2}, mykey3:3333}", "mykey2", "keyinternal2")

AFFICHAGES: 22.2

=JSON("{mykey:1111,mykey2:2222,mykey3:3333}", "mykey2")

AFFICHAGES: 2222

  • INSTRUCTIONS: 
  • Étape 1. appuyez sur ALT + F11
  • Étape 2. Insérer -> Module
  • Étape 3. outils -> références -> tick Microsoft Script Control 1.0
  • Étape 4. coller ceci ci-dessous.
  • Step5. ALT + Q ferme la fenêtre VBA.

Outils -> Références -> Microsoft Script Control 1.0; {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}; C:\Windows\SysWOW64\msscript.ocx

Public Function JSON(sJsonString As String, Key As String) As String
On Error GoTo err_handler

    Dim oScriptEngine As ScriptControl
    Set oScriptEngine = New ScriptControl
    oScriptEngine.Language = "JScript"

    Dim objJSON As Object
    Set objJSON = oScriptEngine.Eval("(" + sJsonString + ")")

    JSON = VBA.CallByName(objJSON, Key, VbGet)

Err_Exit:
    Exit Function

err_handler:
    JSON = "Error: " & Err.Description
    Resume Err_Exit

End Function


Public Function JSON2(sJsonString As String, Key1 As String, Key2 As String) As String
On Error GoTo err_handler

    Dim oScriptEngine As ScriptControl
    Set oScriptEngine = New ScriptControl
    oScriptEngine.Language = "JScript"

    Dim objJSON As Object
    Set objJSON = oScriptEngine.Eval("(" + sJsonString + ")")

    JSON2 = VBA.CallByName(VBA.CallByName(objJSON, Key1, VbGet), Key2, VbGet)

Err_Exit:
    Exit Function

err_handler:
    JSON2 = "Error: " & Err.Description
    Resume Err_Exit

End Function
0
hamish

En utilisant les fonctionnalités JavaScript d’analyse JSON, en plus de ScriptControl, nous pouvons créer un analyseur syntaxique en VBA qui répertoriera chaque point de données à l’intérieur du JSON. Quelle que soit la complexité ou l’imbrication de la structure de données, dans la mesure où nous fournissons un JSON valide, cet analyseur renvoie une structure arborescente complète.

Les méthodes JavaScript Eval, getKeys et getProperty fournissent des blocs de construction pour la validation et la lecture de JSON.

Couplé à une fonction récursive dans VBA, nous pouvons parcourir toutes les clés (jusqu'au nième niveau) d'une chaîne JSON. Ensuite, à l'aide d'un contrôle Tree (utilisé dans cet article), d'un dictionnaire ou même d'une simple feuille de calcul, nous pouvons organiser les données JSON selon les besoins.

Code VBA complet ici. À l'aide des fonctionnalités JavaScript de l'analyse JSON, en plus de ScriptControl, nous pouvons créer un analyseur syntaxique dans VBA qui répertoriera chaque point de données à l'intérieur du JSON. Quelle que soit la complexité ou l’imbrication de la structure de données, dans la mesure où nous fournissons un JSON valide, cet analyseur renvoie une structure arborescente complète.

Les méthodes JavaScript Eval, getKeys et getProperty fournissent des blocs de construction pour la validation et la lecture de JSON.

Couplé à une fonction récursive dans VBA, nous pouvons parcourir toutes les clés (jusqu'au nième niveau) d'une chaîne JSON. Ensuite, en utilisant un contrôle Tree (utilisé dans cet article), un dictionnaire ou même une simple feuille de calcul, nous pouvons organiser les données JSON selon les besoins.

Code VBA complet ici.

0
cyboashu

ceci est un exemple de code vb6, testé ok, fonctionne

à partir des bons exemples ci-dessus, j'ai apporté des modifications et obtenu ce bon résultat

il peut lire les clés {} et les tableaux []

Option Explicit
'in vb6 click "Tools"->"References" then
'check the box "Microsoft Script Control 1.0";
Dim oScriptEngine As New ScriptControl
Dim objJSON As Object

''to use it
Private Sub Command1_Click()
  MsgBox JsonGet("key1", "{'key1': 'value1'  ,'key2': { 'key3': 'value3' } }")''returns "value1"
  MsgBox JsonGet("key2.key3", "{'key1': 'value1'  ,'key2': { 'key3': 'value3' } }") ''returns "value3"
  MsgBox JsonGet("result.0.Ask", "{'result':[{'MarketName':'BTC-1ST','Bid':0.00004718,'Ask':0.00004799},{'MarketName':'BTC-2GIVE','Bid':0.00000073,'Ask':0.00000074}]}") ''returns "0.00004799"
  MsgBox JsonGet("mykey2.keyinternal1", "{mykey:1111, mykey2:{keyinternal1:22.1,keyinternal2:22.2}, mykey3:3333}") ''returns "22.1"
End Sub

Public Function JsonGet(eKey$, eJsonString$, Optional eDlim$ = ".") As String
  Dim tmp$()
  Static sJsonString$
  If Trim(eKey$) = "" Or Trim(eJsonString$) = "" Then Exit Function
  If sJsonString <> eJsonString Then
    sJsonString = eJsonString
    oScriptEngine.Language = "JScript"
    Set objJSON = oScriptEngine.Eval("(" + eJsonString + ")")
  End If
  tmp = Split(eKey, eDlim)
  If UBound(tmp) = 0 Then JsonGet = VBA.CallByName(objJSON, eKey, VbGet): Exit Function

  Dim i&, o As Object
  Set o = objJSON
  For i = 0 To UBound(tmp) - 1
    Set o = VBA.CallByName(o, tmp(i), VbGet)
  Next i
  JsonGet = VBA.CallByName(o, tmp(i), VbGet)
  Set o = Nothing
End Function

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
  Set objJSON = Nothing
End Sub
0
remon78eg