VBAとjar間で対話的に標準入出力を行う

背景

つかっているシステムがVBAだった

VBAクラス

モジュールでなくクラスなので注意

' 対話的にjarとやり取りを行う
' JarOperator.cls
Option Explicit
Dim Wsh As Object
Dim Exec As Object

' jar側の標準入力完了サイン
Const EOS = "EOS"

' 標準出力を取得
Public Function AquireStdOut(St As String) As String

    Exec.StdIn.WriteLine St
    
    Dim Line As String, nLine As String
    Line = vbNullString
    nLine = vbNullString
    
    ' jar側には終わりのサインをつけるようにする
    Do While nLine <> "EOS"
        Line = nLine
        nLine = Exec.StdOut.ReadLine
    Loop
    
    AquireStdOut = Line
End Function

' 実質コンストラクタ
Public Sub SetJarPath(Path As String)
    
    ' jarファイル呼ぶときダブルクオーテーションで囲まないといけない
    Path = """" + Path + """"
    
    Dim cmd As String
    cmd = "java -jar " + Path
    
    Set Wsh = CreateObject("WScript.Shell")
    Set Exec = Wsh.Exec(cmd)
    
    ' 標準入力待ちまで繰り返す
    Exec.StdOut.ReadLine
End Sub

Private Sub Class_Terminate()
    ' 後始末
    Exec.Terminate
    Set Exec = Nothing
    Set Wsh = Nothing
End Sub

使い方

以下のようなjarファイルを作ります

// ShellTest.scala => ShellTest-assembly-0.1.jar
object Test {
var isFirst = true

def main(args: Array[String]): Unit = {
    if (args.length != 0) println(args(0))
    println("launched")
    io("")
}

def io(str: String): Unit = {
    // 実際は分岐させること想定
    str match {
      case _ => {
        if (isFirst) {
        isFirst = false
        } else {
        println(s"echo $str")
        println(s"EOS")
        }
        io(scala.io.StdIn.readLine())
    }
    }
 }
}

javaにPathを通して次のように使います

Option Explicit
Sub Test()
    Dim operator As New JarOperator
    operator.SetJarPath ("ShellTest-assembly-0.1.jar")
    Debug.Print operator.AquireStdOut("うさぎ")
    Debug.Print operator.AquireStdOut("おいし")
    Debug.Print operator.AquireStdOut("かのやま")
    Set operator = Nothing
End Sub

出力

echo うさぎ
echo おいし
echo かのやま