3

I need to call a python script from vba which works fine by using the shell.

Sub CallPythonScript()

        Call Shell("C:\Program Files (x86)\Python27\python.exe C:\Users\Markus\BrowseDirectory.py")

End Sub

But when I try using wsh (because of the wait funcionality) it just won't work anymore.

Sub CallPythonScript()

    Dim wsh As Object
        Set wsh = VBA.CreateObject("WScript.Shell")

    Dim myApp As String: myApp = "C:\Program Files (x86)\Python27\python.exe C:\Users\Markus\BrowseDirectory.py"
    Dim waitOnReturn As Boolean: waitOnReturn = True
    Dim windowStyle As Integer: windowStyle = 1

    wsh.Run """"" & myApp & """"", windowStyle, waitOnReturn

End Sub

However, I used the same code at home and everything worked out just fine, with the difference that there weren't any blanks in the path. So naturally there must be something wrong with the blanks. Help is greatly appreciated.

2
  • I doubt it has ever worked with that path: there are spaces in your paths. How does wsh.Run know how to parse the arguments? At home you certainly had python in C:\python27. Commented Sep 6, 2016 at 19:50
  • Exactly, that's what I meant with "there weren't any blanks in the path". Commented Sep 6, 2016 at 20:11

4 Answers 4

2

The interpreter cannot possibly distinguish directories containing spaces from real arguments unless you protect the directories with quotes.

A workaround, which is actually a better solution, relies on the fact that Python associates .py extension with the installed python interpreter.

Just do this (like you would launch a .bat file):

Dim myApp As String: myApp = "C:\Users\Markus\BrowseDirectory.py"

and your code will work no matter where python is installed (and the problem with spaces vanishes)

This little test in excel worked for me and ran pycrust.py which happens to be in my system PATH:

Sub foo()
  Dim wsh As Object
  Set wsh = VBA.CreateObject("WScript.Shell")

    Dim myApp As String: myApp = "pycrust.py"
    Dim waitOnReturn As Boolean: waitOnReturn = True
    Dim windowStyle As Integer: windowStyle = 1

    wsh.Run myApp, windowStyle, waitOnReturn

End Sub

(I had to simplify your wsh.Run line because it was not working, I suspect that the 256 quotes you added didn't do any good)

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the answer. Sadly neither version works for me. Using the first approach I get error429 ActiveX component can't create object. The second approach results in error method run of object iwshshell3 failed.
1

Did you verify that path takes you directly to the interpreter?

Try this,

Dim myApp As String: myApp = "C:\""Program Files (x86)""\Python27\python.exe C:\Users\Markus\BrowseDirectory.py"

3 Comments

Yes, the path itself is correct. The problem is the spaces in the path. Sadly your solution didn't work for me.
hmm it should. Here's another way to do it, "C:\" & chr(34) & "Program Files (x86)" & chr(34) & "\Python27\python.exe C:\Users\Markus\BrowseDirectory.py" does this work?
Also, wsh.Run myApp, windowStyle, waitOnReturn would be sufficient with my change
0

My script works at my sheet and Python (but I put the sheet and py script in the same folder):

Path = ActiveWorkbook.Path
Pth = """" & Path & "\pythonscript_name.py" & """"
Ph = """" & "C:\Python27\python.exe " & Pth & """"

Dim wsh As Object
Set wsh = VBA.CreateObject("WScript.Shell")
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 1
ErrorCode = wsh.Run(Ph, windowStyle, waitOnReturn)

Comments

0

I do not know if this could have solved your problem, but I encountered the same problem when trying to launch a python script "frozen" with CX-Freeze (from VBA with wsh). Everything worked fine until I changed the folder name of my EXE file to a name with spaces. I did not understand the problem until I read your post and your mention of blank spaces.

I found a function on the internet (maybe here on SO, I don't remember) that gives me the name of the folder in DOS. If like me, you have to pass some parameters that are folder names, then reuse the function to give you the names in DOS.

Here is the function found on internet:

Public Function GetShortFileName(ByVal FullPath As String) As String

'PURPOSE: Returns DOS File Name (8.3 Format) Give
'FullPath for long file name

'PARAMETERS: FullPath: Full Path of Original File

'RETURNS: 8.3 FileName, or "" if FullPath doesn't
'         exist or file fails for other reasons

'EXAMPLE:
'  GetShortFileName("C:\Nouveau dossier\Nouveau dossier\Nouveau 
dossier\Nouveau dossier\Nouveau dossier\")


Dim lAns As Long
Dim sAns As String
Dim iLen As Integer

On Error Resume Next

'this function doesn't work if the file doesn't exist
If Dir(FullPath) = "" Then Exit Function

sAns = Space(255)
lAns = GetShortPathName(FullPath, sAns, 255)
GetShortFileName = Left(sAns, lAns)

End Function

Here is how you could make your sub :

Dim wsh As Object
Set wsh = VBA.CreateObject("WScript.Shell")
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 1
Dim program_folder_path
Dim file_path

program_folder_path = "C:\Program Files (x86)\Python27\"
program_folder_path = CStr(GetShortFileName(program_folder_path))

file_path = "C:\Users\Markus\BrowseDirectory.py"
file_path = CStr(GetShortFileName(file_path))

wsh.Run program_folder_path & "python.exe" & file_path, windowStyle,_
waitOnReturn

I hope this could help, sorry for my bad english by the way...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.