ExcelからPythonを実行する

Python

はじめに

 Excelでは、WScriptオブジェクトを使ってコマンドプロンプトを使えるので、Pythonを実行する事が可能です。
 WScriptオブジェクトには、RunメソッドとExecメソッドがありますが、両者の違いは以下の通りです。

Runメソッド
・実行するアプリケーションのウインドウスタイルを指定できる
・同期、非同期を指定できる

Execメソッド
・実行するアプリケーションと通信して結果を取得できる

 ここでは簡単なPythonのコードを2つ方法で試してみましょう。

今回使用する Python コード

 今回実験するPythonのコードは、3秒待ってから「Hello Python」と表示する簡単なコードです。

# testPython.py (Pythonコード)

import time

time.sleep(3)
print('Hello Python')

このプログラムを使って挙動を確かめてみましょう。

 testPython.py という名前を付けて保存しておきます。
 後でファイルの場所もフルパスで必要になります。

Runメソッド(WScript.Shell)

 Runメソッドでは、実行するアプリケーションのウィンドウスタイルを第2引数に指定できますが、今回はPythonのコマンドなので必要ありません。
 第3引数には、同期、非同期をBooleanで指定できます同期とは、起動したアプリケーションの終了を待つかどうかです。Falseを指定するとアプリケーションが終了するのを待たずにVBAの処理に戻ってきます。Trueを指定した場合は、アプリケーションの終了を待ってVBAに処理が戻ります。

Sub wsh_run()
    Dim myCommand As String
    Dim wsh As Object
    Dim result As Integer
    
    Set wsh = CreateObject("WScript.Shell")
    
    '実行するコマンド
    myCommand = "python c:\pythonTest\testPython.py"
    
    'コマンドを同期実行
    result = wsh.Run(Command:="%ComSpec% /c " & myCommand, WindowStyle:=0, WaitOnReturn:=True)
    
    If result = 0 Then
        MsgBox ("正常終了")
    Else
        MsgBox ("異常終了")
    End If
    
    Set wsh = Nothing
End Sub

 実行するコマンドは、“python c:\pythonTest\testPython.py としています。
 今回はPythonにパスが通っている状態を想定ていますので、もしパスが通っていない場合は、python.exe のフルパスを指定する必要があります。

 pythonコマンドの後には上記で作ったpythonコードをフルパスでしていします。
 こちらはご自身の環境で適宜変更してください。

 WScript.Shell を wsh で受けて、Run メソッドを実行しています。
 第一引数のCommand にある「“%ComSpec% /c “」はコマンドシェルの 9x系と2000系を自動判定するための記述になります。
 
 第3引数の WaitOnReturn:=True で同期処理を指定していますので、pythonプログラムが終了してから処理が戻ってきます。
 
 Runメソッドの戻り値をresultで受けて結果を判定します。
 
 実行すると、3秒後にメッセージボックスに「正常終了」と表示されるはずです。
 第三引数で WaitOnReturn:=False とした場合は、実行後すぐにメッセージボックスが表示されます。
 この時Pythonプログラムは実行中ということになります。

 いずれの場合も、「Hello Python」という表示は取得できません。

Execメソッド(WScript.Shell)

 Execメソッドでは、Runメソッドと違いPythonコードの戻り値を取得する事ができるようになります。

Sub wsh_exec()
    Dim wsh As Object
    Dim wExec As Object
    Dim Cmd As String
    Dim result As String
    
    Set wsh = CreateObject("Wscript.Shell")
    
    Cmd = "python c:\pythonTest\testPython.py"
    
    Set wExec = wsh.Exec("%ComSpec% /c " & Cmd)
    
    Do While wExec.Status = 0   'コマンドが終わるまで待機
        DoEvents
    Loop
    
    result = wExec.StdOut.ReadAll   '結果を文字列で取得
    
    MsgBox result
    Set wExec = Nothing
    Set wsh = Nothing
End Sub

 途中までは、Runメソッドと一緒です。
 WScript.Shell を wsh で受けて、Execメソッドを実行しています。

 Execメソッドでは、戻り値をWshScriptExecオブジェクトで受けてプロパティを参照する形になります。
 
 コマンドが終了すると、Statusプロパティが 0 になるので、Do While ループを使って終了を待ちます。
 最後に、StdOut.ReadAll で結果を取得できるので、それをメッセージボックスで表示させています。

まとめ

 ExcelVBAでPythonを実行させるなら、戻り値を受け取れるExecメソッドの方が便利かもしれません。
 ただ、StdOut.ReadAllでは、改行も含めた全文となるため取得後にSplit関数などで切り分ける必要性があるかもしれません。

 Pythonが出力する結果を取得したい場合は、テキストファイルやCSVファイルを吐き出させて、後からそれを参照する方法がもあります。
 
 もし、Pythonプログラムを起動して終わりという事であれば、Runメソッドでも良いでしょう。
 この場合は、プログラムの終了を待たないでVBAに戻ってくる事も可能です。
 
 シチュエーションに合わせて工夫してみましょう。

コメント

タイトルとURLをコピーしました