VBAとC#で対話的にプログラムを実行する

VBA、つらいですね。

VBAC#で標準入出力を介し、対話的にプログラムを実行する方法です。

やりたいこと

f:id:usagisagi:20190817132210p:plain

docxというところが闇が深いです。

可搬性を考慮してRegAsmは使用禁止です。最初はC#のdllをラップするC++のdllを作ろうとしましたが、C++はよくわからないので断念しました。

C#

文字列を返すだけの簡単なアプリケーションです。

using System;

class Program {
    static void Main(string[] args) {
        var s = "";
        while (s != "EOF") {
            s = Console.ReadLine();
            Console.WriteLine(s);
        }
    }
}

出力の種類をWindows アプリケーションとすることでコンソールウィンドウを表示せずにすみます。

f:id:usagisagi:20190817132312j:plain

VBA

標準入出力ですがWindows Script Object ModelWshShell.exec()から生まれるWshExecオブジェクトを介して操作できます。

Option Explicit

' 参照設定 -> Windows Script Object Model
Public Sub TestConsole()
    Dim path As String
    path = ThisDocument.path & "\sandbox.exe"  ' フルパス
    
    If Dir(path) = "" Then
        MsgBox path & "が見つかりません"
        Exit Sub
    End If
    
    path = """" + path + """"
    
    Dim wsh As IWshRuntimeLibrary.WshShell
    Set wsh = New IWshRuntimeLibrary.WshShell
       
    On Error GoTo finally
    
    Dim exec As IWshRuntimeLibrary.WshExec
    Set exec = wsh.exec(path)
    
    ' 標準入出力の処理
    exec.StdIn.WriteLine "test1"
    Debug.Print exec.StdOut.ReadLine 

    exec.StdIn.WriteLine "test1"
    Debug.Print exec.StdOut.ReadLine
    
    exec.StdIn.WriteLine "test1"
    Debug.Print exec.StdOut.ReadLine
    
    exec.StdIn.WriteLine "EOF"  
    
finally:
    Set exec = Nothing
    Set wsh = Nothing

End Sub

標準入出力とかよくわからない

AtCoderをやりましょう