8

I'm trying to run a python script from my VBA module. I've tried pretty much every example I've seen on the internet and so for have had no luck. In the VBA module I also run a .bat file, and it works perfectly:

batchname = "U:\Backup Bat File.bat"

Shell batchname, vbNormalFocus

Next I need to run the python script, which is located in the same folder as the excel file. Right now I'm trying out this:

Dim Ret_Val

Dim args

args=Activeworkbook.Path & "\beps_output.py"

Ret_Val = Shell("C:\python34\python.exe" & args, vbNormalFocus)

It doesn't error out, but nothing happens. I'm a little confused at what the "Ret_Val" (return value?) does here, and why it isn't running.

Dhanuka
  • 2,826
  • 5
  • 27
  • 38
EmmaV
  • 81
  • 1
  • 1
  • 2
  • 1
    Shouldn't there be a space between exe and args? Like `Ret_Val = Shell("C:\python34\python.exe " & args, vbNormalFocus)` – Peter Schneider May 29 '15 at 14:47
  • Possible duplicate of [Calling python script from excel/vba](https://stackoverflow.com/q/3567365/608639), [How to call python script on excel vba?](https://stackoverflow.com/q/18135551/608639), [Is there a way to call a Python code in Excel-VBA?](https://stackoverflow.com/q/45410316/608639), [Run and execute a python script from VBA](https://stackoverflow.com/q/30531662/608639), etc. – jww Nov 15 '19 at 12:35

4 Answers4

6

This is running on my PC (Win 7 x64, python 2.7.9):

Sub runpython()
    Dim Ret_Val
    Dim args As String

    args = "W:\programming\python\other_py\sqrt.py"
    Ret_Val = Shell("C:\Program Files (x86)\python27\python.exe" & " " & args, vbNormalFocus)
    If Ret_Val = 0 Then
       MsgBox "Couldn't run python script!", vbOKOnly
    End If
End Sub

Ret_Val will be non-zero if the call succeeds, namely the processID of the launched command. Note that the command will run asynchronuously i.e. the VBA code will continue faster than the external command will terminate.

user1016274
  • 4,071
  • 1
  • 23
  • 19
  • 1
    "`Ret_Val` will be non-zero if the call succeeds." Your code should therefore be: `If Ret_Val = 0 Then` – Axel Sep 12 '17 at 09:35
4

Try adding a space between exe program and file:

Ret_Val = Shell("C:\python34\python.exe " & args, vbNormalFocus)

Also, because Shell is a function that returns a value (variant type - double) with specified arguments, the returned value can be contained in a variable, here as you specify with Ret_Val. You can then add conditional logic and error handling using this value.

Parfait
  • 104,375
  • 17
  • 94
  • 125
2

The difficult part for me was diagnosing what part of the code was not working. The cmd window flashes so fast you can't read the error messages. Just add this line of code above the Shell statement.

Call Shell("cmd.exe", vbNormalFocus)

Step thru the code with F8.

When the cmd window pops up type in the (fullpath)python.exe command and (fullpath)script file.py as you tried with your code. The cmd window now stays open so you can see the messages.

In my case it was a picture that needed a full path instead of assuming it was in the same directory.

Cohen
  • 2,375
  • 3
  • 16
  • 35
M Mirsky
  • 21
  • 2
0

I had the same issue and solved it recently by doing the following:

One line of code worked for me.

Shell("python filepath of .py")

This code essentially opens cmd.exe and writes out the string within the ""

My .py does need my workbook to be closed or else it wont work. so i ended up running a seperate VBA code to duplicate my current workbook and then my python script runs on that duplicate, while my current active workbook executing the above vba code was opened to run the vba code.

Dharman
  • 30,962
  • 25
  • 85
  • 135