VB6でWebサービスを使用しようとしています。私が制御するサービスは現在、SOAP/XMLメッセージまたはJSONを返すことができます。 VB6のSOAPタイプ(バージョン1)がobject
のような単純なタイプではなく、返されたstring
を処理できるかどうかを判断するのは本当に困難です。 int
など。これまでのところ、返されたオブジェクトをVB6で再生するために何をする必要があるかわかりません。
そのため、Webサービスの応答をJSON文字列としてシリアル化できると考えました。 VB6用のJSONパーサーはありますか?
JSON.org をチェックして、さまざまな言語のJSONパーサーの最新リスト(メインページの下部を参照)を確認してください。この記事の執筆時点では、2つの異なるJSONパーサーへのリンクが表示されます。
このVB JSONライブラリの実際の構文は本当に簡単です。
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")
私にとってはうまくいかなかったozmikeソリューションの構築(Excel 2013およびIE10)。その理由は、公開されたJSONオブジェクトのメソッドを呼び出せなかったためです。そのため、そのメソッドはDOMElementに関連付けられた関数を介して公開されています。これが可能であることを知らなかった(そのIDispatchのものでなければなりません)、ありがとうozmike。
Ozmikeが述べたように、サードパーティのライブラリはなく、わずか30行のコードです。
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
次のテストでは、JavaScriptオブジェクトをゼロから構築し、それを文字列化します。次に、オブジェクトを解析して戻し、そのキーを反復処理します。
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
出力
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
これは古い質問ですが、私の答えは「vba json」を検索した後もこのページにアクセスし続ける他の人にとって大きな助けになることを願っています。
私はこれを見つけました page は非常に役に立ちました。 JSON形式のデータ処理を処理するいくつかのExcel互換VBAクラスを提供します。
更新:Evalを使用するよりもJSONを解析するより安全な方法が見つかりました。このブログ投稿はEvalの危険性を示しています... http://exceldevelopmentplatform.blogspot.com/2018/01 /vba-parse-json-safer-with-jsonparse-and.html
このパーティーに遅刻しましたが、申し訳ありませんが、最も簡単な方法は、Microsoft Script Controlを使用することです。 VBA.CallByNameを使用してドリルインするサンプルコード
'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
実際に、JSON/VBA関連のトピックを探る一連のQ&Aを行いました。
Q1 Windows上のExcel VBAで、IDEの大文字化動作によって壊れた解析済みJSONのドット構文トラバーサルの問題を軽減する方法?
Q2 Windows上のExcel VBAでは、解析されたJSON配列をループする方法?
Q3 Windows上のExcel VBAでは、解析されたJSON変数に対して「[オブジェクトオブジェクト]」の代わりに文字列化されたJSON表現を取得する方法?
Q4 Windows Excel VBAでは、JSONキーを取得して「ランタイムエラー '438':オブジェクトはこのプロパティまたはメソッドをサポートしていません」をプリエンプトする方法
Q5 WindowsのExcel VBAでは、解析されたJSON変数について、このJScriptTypeInfoとは何ですか?
「ネイティブ」VB JSONライブラリ。
IE8 +に既にあるJSONを使用することは可能です。これにより、古くなってテストされていないサードパーティのライブラリに依存しなくなります。
amedeusの代替バージョンを参照してください こちら
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
VBからIE.JSONにブリッジできます。
関数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
役に立つと思うなら、賛成票を投じてください
VB6-JsonBag、別のJSONパーサー/ジェネレーター も、ほとんど問題なくVBAにインポートできるはずです。
Jsonは文字列に過ぎないため、構造がどれほど複雑であっても、正しい方法で操作できれば簡単に処理できます。トリックを行うために外部ライブラリまたはコンバーターを使用する必要はないと思います。文字列操作を使用してJSONデータを解析した例を次に示します。
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
VB.NETでExcel-DNAアドインを作成できます。 Excel-DNAは、XLLを.NETで作成できるシンライブラリです。この方法で、.NETユニバース全体にアクセスし、 http://james.newtonking.com/json のようなものを使用できます-カスタムクラスでJSONをデシリアライズするJSONフレームワーク。
興味のある方は、VB.NETを使用してExcel用の汎用Excel JSONクライアントを作成する方法をご紹介します。
http://optionexplicitvba.com/2014/05/09/developing-a-json-Excel-add-in-with-vb-net/
そして、コードへのリンクは次のとおりです。 https://github.com/spreadgit/Excel-json-client/blob/master/Excel-json-client.dna
.Netコンポーネントを使用することをお勧めします。 Interop を介してVB6から.Netコンポーネントを使用できます-ここに tutorial があります。私の推測では、.Netコンポーネントは、VB6用に作成されたものよりも信頼性が高く、より適切にサポートされます。
Microsoft .Netフレームワークには、 DataContractJsonSerializer や JavaScriptSerializer などのコンポーネントがあります。 JSON.NET のようなサードパーティのライブラリを使用することもできます。
これは古い投稿であると理解していますが、最近、古いVB6アプリにWebサービスの消費を追加しているときにつまずきました。受け入れられた回答(VB-JSON)はまだ有効であり、機能しているように見えます。しかし、ChilkatがRESTおよびJSON機能を含むように更新されていることを発見しました。貼り付けられたJSONデータを解析します。
Excel CELLの数式
=JSON2("{mykey:1111, mykey2:{keyinternal1:22.1,keyinternal2:22.2}, mykey3:3333}", "mykey2", "keyinternal2")
ディスプレイ:22.2
=JSON("{mykey:1111,mykey2:2222,mykey3:3333}", "mykey2")
ディスプレイ:2222
ツール->参照-> 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
JSONを解析するJavaScript機能を使用して、ScriptControlの上に、VBAでパーサーを作成し、JSON内のすべてのデータポイントをリストできます。データ構造がどの程度ネストまたは複雑であっても、有効なJSONを提供する限り、このパーサーは完全なツリー構造を返します。
JavaScriptのEval、getKeys、およびgetPropertyメソッドは、JSONを検証および読み取るためのビルディングブロックを提供します。
VBAの再帰関数と組み合わせると、JSON文字列のすべてのキー(最大nレベルまで)を反復処理できます。次に、Treeコントロール(この記事で使用)またはディクショナリ、または単純なワークシートを使用して、必要に応じてJSONデータを配置できます。
完全なVBAコード:JSONを解析するJavaScript機能を使用して、ScriptControlの上に、VBAでパーサーを作成して、JSON内のすべてのデータポイントをリストできます。データ構造がどの程度ネストまたは複雑であっても、有効なJSONを提供する限り、このパーサーは完全なツリー構造を返します。
JavaScriptのEval、getKeys、およびgetPropertyメソッドは、JSONを検証および読み取るためのビルディングブロックを提供します。
VBAの再帰関数と組み合わせると、JSON文字列のすべてのキー(最大nレベルまで)を反復処理できます。次に、Treeコントロール(この記事で使用)またはディクショナリ、または単純なワークシートを使用して、必要に応じてJSONデータを配置できます。
これはvb6のサンプルコードで、テスト済みです。
上記の良い例から、変更を加えてこの良い結果を得ました
キー{}および配列[]を読み取ることができます
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