• 締切済み

VBAのJScriptのeval()の挙動について

VBAのコードを調べていますが、 JScriptで記述されている部分があり、 この部分でよく分からない挙動があるので教えてください。 (JSONデータをパースしているコードです) 具体的には、(実際のコードを簡略化したもの) ---------------------------------------- Sub test() Dim x As String Dim sc As Variant Dim y As String x = "{""A"":""d"",""B"":""e"",""C"":""f""}" Set sc = json_perse(x) y = sc.CodeObject.getValue("B") Debug.Print y End Sub Public Function json_perse(ByVal x As String) As Variant Dim sc As Object Set sc = CreateObject("ScriptControl") With sc .Language = "JScript" .AddCode "function getValue(){ var $tmp=''; for(var $i = 0; $i < arguments.length; $i++){ $tmp += ""['"" + arguments[$i] + ""']""; } return eval('e' + $tmp); }" .AddCode "var e = eval(" & x & ");" End With Set json_perse = sc End Function ------------------------------------------ のコードを実行すると、 getValue()の引数で指定した文字列(ここではB) の後の:の後の文字(ここではe)が返されますが、 なぜ、このようになるのかがよく分かりません。 この処理をしている部分を抽出すると ------------------------------------- function getValue(){  var $tmp='';  for(var $i = 0; $i < arguments.length; $i++){  $tmp += ""['"" + arguments[$i] + ""']"";  }  return eval('e' + $tmp); } var e = eval(" & x & "); ------------------------------------- となっていて、 eval()は、文字列として指定されたコードをJavaScriptのコードとして評価する ということですが、 eval(" & x & ")とeval('e' + $tmp)の部分が何をしているのかがよく分かりません。 なぜ、このコードを実行すると、 $tmpの文字(この場合はB)の後の:の後にある値が取得できるのでしょうか。

みんなの回答

回答No.1

eval(" & x & ") このxは、json_perse(ByVal x As String)の括弧の中にあるxです。なので、今回のコードでは、"{""A"":""d"",""B"":""e"",""C"":""f""}"が渡されます。なので、 e = {"A":"d","B":"e","C":"f"}; となり、eに連想配列が代入されます。 eval('e' + $tmp)の$tmpは、arguments.length=1、argumenst[0]="B"の場合、"['B']"になります。なので、実行されるコードはe['B']となり、連想配列eから'B'に該当する部分を取得するので、'e'が返ってきます。

yam2012
質問者

お礼

どのようなことが行われているのかがよく理解できました。 とても分かりやすい説明ありがとうございました。 なお、今回の現象を調べるために、 さらにコードを簡略化して調べていたのですが、 下記のように引数なしで固定値を返すようにすると、 なぜか、引数を指定しないと、正しい値が戻ってきません。 もし、この理由が分かりましたら教えていただけないでしょうか。 よろしくお願いします。 ---------------------------------------------- Sub test()  Dim x As String  Dim sc As Variant  Dim y As String  x = "{""A"":""d"",""B"":""e"",""C"":""f""}"  Set sc = json_perse(x)  y = sc.CodeObject.getValue() '【変更箇所】  'y = sc.CodeObject.getValue("") ' これはOK  Debug.Print y End Sub Public Function json_perse(ByVal x As String) As Variant  Dim sc As Object  Set sc = CreateObject("ScriptControl")  With sc   .Language = "JScript"   .AddCode "function getValue(){ return eval('e[""B""]'); }" '【変更箇所】   .AddCode "var e = eval(" & x & ");"  End With  Set json_perse = sc End Function ------------------------------------------------

関連するQ&A

  • Eval関数を使いたい!ドキュメントにある宣言とはなに?

    Eval関数を使いたい!ドキュメントにある宣言とはなに? DataBinder.Eval メソッド にある DataBinder.Eval (Object, String, String) 実行時にデータ バインディング式を評価し、 結果を要求側のブラウザに表示されるテキストとして書式化します。 を使いたいです。 Visual Studio 2005のドキュメントで見つけました。 ドキュメントにある宣言とはなんですか? Visual Basic (宣言) Public Shared Function Eval ( _ container As Object, _ expression As String, _ format As String _ ) As String Visual Basic (使用法) Dim container As Object Dim expression As String Dim format As String Dim returnValue As String returnValue = DataBinder.Eval(container, expression, format) 宣言と使用方法が載っていましたが、使い方がわかりません・・・ ~~~~~~~~~~~~~~~~~~~~~~ 以下を書くと「名前'Eval'は宣言されていません」とエラーが出ます。 宣言がわかっていないので、当たり前といえば、当たり前です。 Dim myWork As String = "1+2+3+4" Dim myTotal As String = "" myTotal = Eval("myWork") これが使えるようにするにはどうしたらいいか教えてください!

  • eval、$.eachで順番が入れ替わるのはなぜ?

    JSONデータをeval後、$.each(jQuery)を通すと、 順番が入れ変わってしまうのですが、どういう原因が想定されるでしょうか? <JSON> data: { "5":{"id":"5","name":"5","menu1":"24"}, "9":{"id":"9","name":"9","menu1":"12"} "1":{"id":"1","name":"1","menu1":"4"}, "2":{"id":"2","name":"2","menu1":"2"}, } ※「menu1」降順で予めソート <コード> $.get("data.php?"+○○, function(data){ var list = eval( '(' + data + ')' ); $.each(list,function(i) { 上記コードを通すと、 Chromeで見た際、データがid順に並び変わります。 (FireFoxだと、元の順番通りです) <質問> 「eval」もしくは「$.each」を利用すると、 データの順番が入れ替わることがあるのでしょうか? 入れ替わらないためには、どうすれば良いのでしょうか?

    • ベストアンサー
    • AJAX
  • vbaで配列に値を格納する場合

    vbaで配列に値を格納する場合 変数の宣言はどちらを使った方が良いのでしょうか? Sub Sample1() Dim i As Long Dim myStr As String Dim tmp() As String myStr = "a,i,u,e,o" tmp = Split(myStr, ",") End Sub か Sub Sample1() Dim i As Long Dim myStr As String Dim tmp As Variant myStr = "a,i,u,e,o" tmp = Split(myStr, ",") End Sub でも問題なく動くのですが、 Variant型での宣言はあまりしない方が良いですか? あと Dim tmp() As String ならエラーにならないのですが Dim tmp As String だとエラーになってしまう理由がよくわからないので教えて頂けますか?

  • コードの簡略化 VBA

    dim a as string dim b as string dim c as string dim d as string dim e as string dim f as string dim g as string dim h as string dim i as string a = "○○" b = "○○" c = "○○" d = "○○" e = "○○" f = "○○" g = "○○" h = "○○" i = "○○" 上記のような形でたくさん宣言しているのですが、 実際はもっとあり、これだととても長いコードになってしまいます(・・;) なんとか簡略化したいとは考えたのですがよい方法が見つからず 皆さんよろしくお願いいたします_(_^_)_

  • javascript

    var sum = function(){ var result = 0; for(var i = 0; i < arguments.length; i++){ var tmp = arguments[i]; result += tmp; } return result; } document.writeln(sum(1, 3, 5, 7, 9)); このプログラムと function sum(){ var result = 0; for(var i = 0; i < arguments.length; i++){ var tmp = arguments[i]; result += tmp; } return result; } document.writeln(sum(1, 3, 5, 7, 9)); このプログラムでは実行結果は同じですが、 どちらのほうが良いプログラムなのでしょうか?

  • コマンドプロンプトで実行したら・・・

    Function SpaceDelete(dt As String) As String Dim tmp As String Dim Aftr As String Dim i As Integer For i = 1 To Len(dt) tmp = Mid(dt, i, 1) If tmp <> " " And tmp <> " " Then Aftr = Aftr & tmp End If Next i SpaceDelete = Aftr End Function test.vbs(1,25) Microsoft VBScript コンパイル エラー: ')'がありません。とエラーがでます。 どこが問題かわかりません。 どなたか教えて頂けないでしょうか。 宜しくお願いします。

  • 【VBA】入れ子のユーザー定義型

    閲覧ありがとうございます。 入れ子になってるユーザー定義型(構造体)に、値を代入する処理を抽象化したいのですが、上手くできません。 色々間違っているかもしれませんが、やりたいことのイメージは下のような感じです。 Private Type id kind As String memberId As String End Type Private Type items kind As String name As String id As id End Type sub main() (省略) Dim tmp As Variant tmp = jsonのレスポンスが1行ずつ配列で入ってる Dim items() As items items() = loading(tmp) (省略) End Sub Private Function loading(ByVal tmp As Variant) Dim pair() As Variant pair = Split(tmp, ":") Dim head As String Dim items() As items  If 末尾が"{"だったら、 If pair(0) = "{" then head = "items(0)" else if pair(1) = "{" then head = head & pair(1) Else head.pair(0) = pair(1) ←pair(0)は名前、pair(1)は値がそれぞれ入っている endif loading = items() End Function 説明が下手すぎてすみません。 実際は、もっとたくさん入れ子になっている為、抽象化できないと非常に困ります。 答えられそうだけど質問の意味をもう少しきちんと…ということであれば努力しますので、なんとか、よろしくお願いいたします。

  • 二次元配列のVBA

    二次元配列のVBAの書き方がよくわからないのですが、 私が作ったサンプルプログラムのSub 二次元()において 二次元配列で表すにはどうすればいいのでしょうか? Sub 二次元()では 配列を格納する変数はtmpしか使っていませんが もう一つ配列を格納する用の変数を作ればいいのでしょうか? 数字とアルファベットは別々に取り出したいです。 ----------------------------------------------------- Sub 一次元() Dim myStr As String Dim tmp As Variant Dim i As Long For i = 1 To 5 myStr = myStr & "," & i Next myStr = Mid(myStr, 2) tmp = Split(myStr, ",") For i = LBound(tmp) To UBound(tmp) Debug.Print tmp(i) Next i End Sub Sub 二次元() Dim myStr As String Dim tmp As Variant Dim i As Long For i = 1 To 5 myStr = myStr & "," & i & "と" & Chr(64 + i) Next myStr = Mid(myStr, 2) tmp = Split(myStr, ",") For i = LBound(tmp) To UBound(tmp) Debug.Print tmp(i) Next i End Sub

  • VBAについて質問させて下さい。

    VBAについて質問させて下さい。 Sub Exsample() Dim a As String a = "aaa" MsgBox Ketugou(a) End Sub Function Ketugou(x As String) Ketugou = x End Function このサンプルコードについて質問が2つあります。 【質問1】 なぜ x=a、 と言う式はないのに xにが代入されるのでしょうか? 【質問2】 なぜ MsgBox Ketugou(a) では aaa(aaa) とならないのでしょうか? a = "aaa" Ketugou= "aaa" になってるはずですが。 よろしくお願い致します。

  • 【VBA】Function内のValueについて

    VBAについて教えてください。 以下のFunctionで定義したCells(i, "○").Valueに値が入力されません。 iのカウントアップまでは正常に行われています。 このFunctionはExcel上で関数で「=Order_Buy(1111,テスト)」のようにして呼び出しています。 ちなみにSubで定義して単体で実行すると該当セルに値が入力されました。 何が問題か、ご教授いただけないでしょうか Public Function Order_Buy(ByVal code As String, ByVal meigara As String) As String Dim i As Integer i = 3 Do Until Cells(i, "M") = "" i = i + 1 Loop Cells(i, "M").Value = Now Cells(i, "N").Value = code Cells(i, "O").Value = meigara Order_Buy = "test" End Function

専門家に質問してみよう