For work, I'm trying to run a Python script from an Excel VBA macro.
The macro is as follows -
Sub Plot()
Shell "C:\Users\maheshda\AppData\Local\Continuum\Anaconda3\python.exe C:\Users\maheshda\Tool\Tool\Main.py", vbNormalFocus
End Sub
The script runs just fine when run from the command line, but unfortunately, because I'm using relative filepaths in the Python script (at one point, I call files from '../Input/') the script crashes because the current working directory isn't C:\Users\maheshda\Tool\Tool.
How can I change the working directory from within the macro? Thank you!
This is a trivial task in VBA, use ChDir:
ChDir Statement
Changes the current directory or folder.
Syntax
ChDir path
The required path argument is a string expression that identifies which directory or folder becomes the new default directory or folder. The path may include the drive. If no drive is specified, ChDir changes the default directory or folder on the current drive.
Since your main.py resides in C:\Users\maheshda\Tool\Tool\, use the following right before calling the Python script:
ChDir "C:\Users\maheshda\Tool\Tool"
Or (since it is on drive C):
ChDir "\Users\maheshda\Tool\Tool"
Extending on Wiktor Stribiżew's answer and comments, the sub below can be used to change the Current Directory in any case.
Public Sub Change_Current_Directory(NewDirectoryPath as string)
Dim CurrentDirectoryPath as string
CurrentDirectoryPath = curdir
if Strings.StrComp(Strings.Left(CurrentDirectoryPath,2), Strings.Left(NewDirectoryPath,2), vbTextCompare) then
ChDrive Strings.Left(NewDirectoryPath,1)
end if
ChDir NewDirectoryPath
End Function
Happy coding!
FCastro, why did you bother with that StrComp line? And, for that matter, why bother with the Strings object?
I suppose if the drive were external and hadn't been accessed yet it might take a moment, but as long as the path is not expected to be a USB/CD/DVD/etc..., then:
Public Sub Change_Current_Directory(NewDirectoryPath as string)
ChDrive Left(NewDirectoryPath,1)
ChDir NewDirectoryPath
End Function
If your behavior is to open an excel window and then open your recent file, please note that you should not forget to add change Drive and then change Directory into your VBA code.
Cause the Excel always start with the default Directory even it's just open your recent file !
Dim ThisWorkbookPath As String
Dim ThisWorkbookPathParts As Variant
ThisWorkbookPath = ThisWorkbook.Path
ThisWorkbookPathParts = Split(ThisWorkbookPath, _
Application.PathSeparator)
ChDrive ThisWorkbookPathParts(LBound(ThisWorkbookPathParts))
ChDir ThisWorkbookPath
Related
The following code checks to see if a folder exists and, if not, creates it. The code works, but a handle that points to the folder is left open if it already exists, which prevents the folder from being deleted or renamed until Outlook.exe closes. I do not understand why this is happening or what to do about it, but a handle should not be open after the folder is checked and potentially created.
Sub Test()
Folder = Environ("USERPROFILE") & "\Desktop\NewFolder\"
Result = Dir(Folder, vbDirectory)
If Result = vbNullString Then
MkDir Folder
End If
End Sub
The first time through the code, the folder is successfully created and no file handles are open:
However, the second time through the code, the folder already exists. MkDir does not execute, but a file handle is left open presumably after Dir executes:
I have tried everything I could find to close all open file handles, but nothing has worked. Any help would be greatly appreciated.
Based on the comments from braX, I was able to prove that the Dir call was somehow responsible for the leftover handle. Calling Dir again on a non-existent folder caused the handle to be released, which solved my problem.
A better solution, which was also suggested by braX, is to use a File System Object. Here is a working solution:
Sub Test()
Dim FSO As FileSystemObject
Set FSO = CreateObject("Scripting.FileSystemObject")
Folder = Environ("USERPROFILE") & "\Desktop\NewFolder\"
If Not FSO.FolderExists(Folder) Then
MkDir Folder
End If
End Sub
Thanks, braX!
My latest attempt to solve my problems when calling a .exe with an input argument from Excel-VBA uses this script:
Sub RunProgram()
Dim wsh As Object
Set wsh = VBA.CreateObject("WScript.Shell")
ChDir "\\path\folder1\folder2\"
StartExeWithArgument
......
End Sub
Public Sub StartExeWithArgument()
Dim strProgramName As String
Dim strArgument As String
strProgramName = "program.exe "
strArgument = "datafile.gdp"
Call Shell("""" & strProgramName & """ """ & strArgument & """", vbNormalFocus)
End Sub
The path I set as the working directory is the working directory of the .exe program, and the location of the input file datafile.gdp. However, this current script calls the .exe without loading the argument file and the calculations the .exe is supposed to run do not occur. Instead the .exe launches to its main page as though I clicked a desktop shortcut to start a new project. When loaded correctly, the .gdp file should cause the calculation to initiate and run in the background without ever appearing to the user.
If I change the path of the input file to:
strArgument = "\\path\folder1\folder2\datafile.gdp"
But keep everything else the same, the .exe launches and calculates automatically, but wants to write files in the following duplicated directory, (all prefixed with the name of the input file):
\\path\folder1\folder2\PATH\FOLDER1\FOLDER2\
If I create the file path for it to operate in everything operates as it should, BUT the path is actually 6 folders deep in reality and this is all being duplicated, meaning the files are too deep to be backed up on our system. So I need to launch the program and have it operating without this duplication of the directory. It works fine when not launched from this VBA script, and worked fine before the .exe was updated by an external company.
Why can the Call Shell command find the .exe without a path, but I
need to provide a path for the argument?
strArgument = ... requires a path to find the argument file, despite the file being in the current directory, providing the path seems to pass a duplicated path to the .exe causing it to crash if I don't create the folders representing the duplicated directory so it can operate within them. Is there something very basic I am missing regarding directories?
My previous up-voted but unanswered question here provides more context.
I am running a sub from a userform that is supposed to run an exe file, found in the working folder, as follows:
Sub RunProcessor()
If MsgBox("Run simulation?", vbYesNo) = vbNo Then
Exit Sub
Else
ChDir ThisWorkbook.Path
Shell ("runsims.exe")
End If
End Sub
This was working fine on my local drive, but started to fail when I moved everything to a server drive (Run-time error 5 on the Shell function call line).
I know in cmd, when you are working on the C: drive and do a cd L:\...\...\ call, you then need to enter L: as well, so I tried to insert this line of code above the other Shell call: Shell (Left(ThisWorkbook.Path, 2)) but this also failed. How can I have "runsims.exe" run, given that it is always in the current working drive?
ChDir will only work to change the current directory to another on the same drive - you need to use ChDrive first if you want to switch to a folder on a different drive.
Better yet, pass the full path to Shell and skip changing the current directory.
Sub RunProcessor()
If MsgBox("Run simulation?", vbYesNo) = vbYes Then
Shell (ThisWorkbook.Path & "\runsims.exe")
End If
End Sub
I am running a sub from a userform that is supposed to run an exe file, found in the working folder, as follows:
Sub RunProcessor()
If MsgBox("Run simulation?", vbYesNo) = vbNo Then
Exit Sub
Else
ChDir ThisWorkbook.Path
Shell ("runsims.exe")
End If
End Sub
This was working fine on my local drive, but started to fail when I moved everything to a server drive (Run-time error 5 on the Shell function call line).
I know in cmd, when you are working on the C: drive and do a cd L:\...\...\ call, you then need to enter L: as well, so I tried to insert this line of code above the other Shell call: Shell (Left(ThisWorkbook.Path, 2)) but this also failed. How can I have "runsims.exe" run, given that it is always in the current working drive?
ChDir will only work to change the current directory to another on the same drive - you need to use ChDrive first if you want to switch to a folder on a different drive.
Better yet, pass the full path to Shell and skip changing the current directory.
Sub RunProcessor()
If MsgBox("Run simulation?", vbYesNo) = vbYes Then
Shell (ThisWorkbook.Path & "\runsims.exe")
End If
End Sub
in VBA there is a ChDir function that allows to set/change the current directory.
That Current Directory is also affected by a user browsing through his drives/folders from Access (or Excel), even if he clicks Cancel in the end without opening anything.
My question is: in the later case, how do I retrieve the Current Directory ?
Note: the CurrentDirectory has nothing to do with the folder of the CurrentDb!
You want CurDir$:
?CurDir$
c:\temp
ChDir "c:\windows\"
?CurDir$
c:\windows
The complement to the ChDir command in VBA is the CurDir function.
on VBS
Dim WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
WScript.Echo WshShell.CurrentDirectory