カレンダー

04 | 2016/05 | 06
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 - - - -

プロフィール

YOS G-spec

ハンドルネーム:YOS G-spec
もう一つの名:んらとらん
性別:男
生息地:千葉県
職業:社会人3年生

好きなゲームシリーズ
・ロックマン全般
・モンスターハンター
・討鬼伝
・太鼓の達人
・ドラムマニア
・モンスターファーム
・サルゲッチュ
・チョロQ
・マリオカート
・DJMAX Potable
・リズム天国
・グランツーリスモ
・ポケットモンスター

【フレンドコードまとめ】
【所持ゲーム表】

なんか色々と適当で中途半端な人です。

ついったー(気まぐれ更新)
ついろぐ(ついったーまとめログ)
ギガスペックツール
ギガスペックチャット
過去の産物

メール
スカイプID:yos_g-spec

新太鼓番:3348-9507-7550
3DSフレンドコード:1289-8444-6710
とび森夢番地:3500-0140-1697



最近の記事

最近のコメント

  • 01/01:YOS G-spec

  • 12/17:ばぜるこあ

  • 01/04:YOS G-spec

  • 11/15:暇神

  • 12/06:YOS G-spec

  • 12/05:くま☆

  • 08/22:YOS G-spec

カテゴリー

VBAからNode.jsを呼び出すモジュール

とりあえず、完成しました。
初めてGitHugというの使ったのでそこで投げておきます。
GitHug:nodefunc_VBA

VBAからNode.jsを呼び出すモジュール続報

今日も適当にソースぽい投げ。
jsもモジュール化したし、もう大体使える。
あとはjsから返す値に型変換加えておきたいなぁ。
ただちょっと調べた感じだとtypeofはなかなか面倒臭そうだ。

Option Explicit

Sub main()
Dim ask As Variant
ask = Array("hur_", "nara", 100)
Debug.Print nodefn("vbaret", ask, "30*80")

End Sub

Function nodefuncPath() As String
nodefuncPath = ThisWorkbook.Path
End Function

Function nodemain() As String
nodemain = "main.js"
End Function

Function nodefn(func As String, ParamArray args() As Variant) As Variant
Dim WSH As Object
Dim Command As String
Set WSH = CreateObject("WScript.Shell")

Dim i As Long
For i = 0 To UBound(args)
If 0 <= UBound(args) Then
If InStr(TypeName(args(i)), "()") Then
args(i) = Join(Array(Join(args(i), "$Array$"), TypeName(args(i)(0)) & "()"), ":")
Else
args(i) = Join(Array(args(i), TypeName(args(i))), ":")
End If
End If
Next

Const tempfile As String = "Temp$GIy0qPan"

WSH.CurrentDirectory = nodefuncPath

Command = Join(Array( _
"node ", nodemain, " " & func & IIf(0 <= UBound(args), " " & Join(args, " "), "") _
), "")

WSH.Run Join(Array("%ComSpec% /c ", Command, " > ", tempfile, " 2>&1 ", _
" & Echo %ErrorLevel% >>", tempfile), ""), 0, True '

If Dir(nodefuncPath & "\" & tempfile) = "" Then
Debug.Print "Error:結果の未取得"
Exit Function
End If

Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim stream As Object
Set stream = fso.OpenTextFile(nodefuncPath & "\" & tempfile, 1)

Dim return_txt As String
return_txt = stream.ReadAll

Set stream = Nothing
Set fso = Nothing
Kill nodefuncPath & "\" & tempfile

Dim return_array As Variant
return_array = Split(Replace(Replace(return_txt, vbCrLf, vbLf), vbCr, vbLf), vbLf)
If return_array(UBound(return_array) - 1) = 0 Then
return_txt = ""
For i = 0 To UBound(return_array) - 2
return_txt = Join(Array(return_txt, return_array(i)), vbLf)
Next
return_txt = Mid(return_txt, 2)

If Not InStr(return_txt, "$ReturnArgs$") Then
nodefn = return_txt
Else
nodefn = Split(return_txt, "$ReturnArgs$")
End If
Else
For i = 0 To UBound(return_array) - 2
Debug.Print return_array(i)
Next
nodefn = Nothing
End If
Set WSH = Nothing
End Function


//process.argv=["","","vbaret", "daba:darr:string", "500:Integer"];
var nf=require("./nodefunc");
eval(nf.func());

function vbaret(x,y){
console.log(x);
console.log(y);
nf.return_VBA("Hello VBA!");
}


module.exports=new function(){
this.func=function(){
process.argv.shift();
process.argv.shift();
var runfunc=process.argv.shift()+"(";
var args="";

if(0<process.argv.length){
for(var i=0;i<process.argv.length;i++){
var arg=process.argv[i].split(/\:/);
var jstype=arg.pop();
var arg_str=arg.join("\:");
args+=","+typearray(jstype,arg_str);
}
args=args.substr(1);
}
runfunc+=args+")";
return runfunc;
};

this.return_VBA=x=>{console.log(""+x);process.exit();};

function typearray(jstype,arg_str){
if(/\(\)/.test(jstype)){
var arg_strs=arg_str.split("$Array$");
for(var i=0;i<arg_strs.length;i++){
arg_strs[i]=typecast(jstype.replace("()",""),arg_strs[i]);
}
return "["+arg_strs.join(",")+"]";
}
else {
return typecast(jstype,arg_str);
}
}

function typecast(jstype,arg_str){
switch(jstype.toLowerCase()){
case "byte":
case "integer":
case "long":
case "decimal":
case "currency":
return "parseInt("+arg_str+",10)";
case "single":
case "double":
return "parseFloat("+arg_str+")";
case "boolean":
return "!(Boolean("+arg_str+")||"+arg_str+".toLowerCase()=='false')";
case "date":
return Parse.date("date");
case "char":
case "string":
case "variant":
default:
return "'"+arg_str+"'";
}
}
};

VBAからNode.jsにアクセスするテスト

今日は時間がないので説明は略。
コンソールでてくるの嫌だからExec避けたいけど何かいい方法ないだろうか。
Runで普通にtxtファイル書かせるかなぁ…
なんにせよどうやって返り値を得るかが課題か。

Sub main()
nodefunc "vbaret", "daba:darr:string", "10.54:number"
End Sub

Function nodefunc(func As String, ParamArray args() As Variant) As Variant
Dim WSH, wExec, sCmd As String, Result As String
Set WSH = CreateObject("WScript.Shell")
sCmd = "node C:\nc.js " & func & IIf(0 <= UBound(args), " " & Join(args, " "), "")
Set wExec = WSH.Exec("%ComSpec% /c " & sCmd)
Do While wExec.Status = 0
DoEvents
Loop
Result = wExec.StdOut.ReadAll & "hoge"

Debug.Print Result
Set wExec = Nothing
Set WSH = Nothing
End Function


var return_VBA=x=>{process.stdout.write(""+x);process.exit();};

process.argv.shift();
process.argv.shift();
var runfunc=process.argv.shift()+"(";
var args=""

if(0<process.argv.length){
for(var i=0;i<process.argv.length;i++){
var arg=process.argv[i].split(/\:/);
var jstype=arg.pop();
var arg_str=arg.join("\:");
if(jstype!=null){
switch(jstype.toLowerCase()){
case "int":
case "integer":
case "long":
arg_str="parseInt("+arg_str+",10)";
break;
case "single":
case "double":
case "number":
arg_str="parseFloat("+arg_str+")";
break;
case "bool":
case "boolean":
arg_str="!(Boolean("+arg_str+")||"+arg_str+".toLowerCase()==\"false\")";
break;
case "string":
arg_str="\""+arg_str+"\"";
default:
}
}
args+=","+arg_str;
}
args=args.substr(1);
}
runfunc+=args+")";
eval(runfunc);

function vbaret(x,y){
console.log(x);
console.log("y+30="+(y+30));
return_VBA("Hello VBA!");
}

色々な言語で即時関数

JavaScriptでよく見る怪しい挙動のこれ→(function(){})()
が他の言語でもどの程度可能なのか調べてみたら意外に出来たのでまとめておく。
まず、JavaScriptのテストケース
var print=console.log;
print((function(x){print(x);return x*x;})(5));

5
25

のように表示される。
ES6以降で、
var print=x=>console.log(x);
print((x=>{print(x);return x*x;})(5));

TypeScript
var puts:any=console.log;
puts(((x:number)=>{puts(x);return x*x;})(5));

Ruby
puts((->(x)do puts(x);return x*x end).(5))

Lua
print((function(x)print(x)return x*x end)(5))

R
print<-function(x)cat(x,"\n")
(function(){print((function(x){print(x);x*x})(5))})()

CommonLisp
(print((lambda(x)(print x)(* x x)) 5))

Clojure
(println((fn[x](println x)(* x x)) 5))

C#(scriptcs版)
Action<int> printi=x=>Console.WriteLine(x);
printi(new Func<int,int>(x=>{printi(x);return x*x;})(5));

VB.NET
module program
  dim print as action(of object)=sub(x)Console.WriteLine(x)

  sub main
    print(ctype((function(x)
        print(x):return x*x:end function),func(of long,long))(5))
  end sub
end module

C#とVBは大分苦しいけど可能なことは可能らしい。

FreeBasic

FizzBuzz

' FreeBasic '
sub main
for i as integer=0 to 100
if i mod 3=0 and i mod 5=0 then
print "Fizz Buzz"
elseif i mod 3=0 then
print "Fizz"
elseif i mod 5=0 then
print "Buzz"
else
print str(i)
end if
next
end sub
main


たらい回し関数

#Include "string.bi"

function tarai(x as long,y as long,z as long) as long
if x<=y then
return y
else
return tarai(tarai(x-1,y,z),tarai(y-1,z,x),tarai(z-1,x,y))
end if
end function

dim atime as double=timer
print tarai(12,6,0)
dim ztime as double=timer
print "Time:"&format(ztime-atime,"0.000")&"[s]"
dim ext as string
line input "",ext


構造体定義(クラスは不可)

type person
dim name as string
dim age as integer
end type

function person(myname as string,myage as integer) as person
dim mytype as person
mytype.name=myname
mytype.age=myage
return mytype
end function

sub main
dim student as person = person("bob",13)
dim teacher as person = person("john",30)

print "名前 : " & student.name
print "年齢 : " & student.age
print "名前 : " & teacher.name
print "年齢 : " & teacher.age
end sub
main


速度的にはコンパイラとして一般的なくらい。
Node.jsより少し早いかなと言ったところ。
BASICは好きなのでおもちゃにするならいい感じ。

| TOP | NEXT