Calling powershell or ruby script by VBA, ideally take output to Excel or point user to output path - excel

I need Excel VBA to call another script language using shell. Ideally, also returning its output, but if that is hard to do, just to execute that other script and tell the user in a pop-up MessageBox where to get the output from and paste it into the Excel file.
I tried several ways, including (I took out some full file names):
pscmd = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noexit -ExecutionPolicy Bypass -File ......\.....ps1"
or
Shell("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ""........ps1""", vbNormalFocus) - with full path to powershell or not
or
Shell("ruby.exe ""C:\testsoft\test.rb", "C:\testsoft\tst.txt""", vbNormalFocus)
or
Shell("powershell -ExecutionPolicy Bypass "".....ps1 -input """ & pathVariable & """", 1)
or
Sub RunPowershellScript()
strCommand = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noexit -ExecutionPolicy Bypass -File ""C:\testsoft\mdruby-nolog.ps1"""
Set wshShell = CreateObject("WScript.Shell")
Set WshShellExec = wshShell.Exec(strCommand)
strOutput = WshShellExec.StdOut.ReadAll
MsgBox strOutput
End Sub
but all to no avail.
It does not work at all with running a ruby script or powershell script or opening cmd.
For example, calling up some programs that I tested work though:
strCommand = "ping.exe 127.0.0.1"
strCommand = "notepad.exe" ' works even with specifying a file to open
strCommand = "calc.exe"
My powershell or ruby scripts shall calculate MD5 checksums of PDFs created from Excel using VBA. They work on their own, just fine.
Is there an easy way?

Related

Excel VBA Workbook_Open does not work when Excel is already open

I was trying to automate VBA run with its file opening from command line as below:
cmd.exe /C set MacroName=MyMacro \& EXCEL.EXE C:\\_documents\\Book2.xlsm
The VBA scripts and files are as follows:
Book2.xlsm/Module1
Sub MyMacro()
MsgBox "MyMacro is running..."
End Sub
Book2.xlsm/ThisWorkbook
Private Sub Workbook_Open()
Dim strMacroName As String
strMacroName = CreateObject("WScript.Shell").Environment("process").Item("MacroName")
If strMacroName <> "" Then Run strMacroName
End Sub
Now, the above cmd command does work, expectedly notifies me with the MsgBox, when Excel is not open. But it does not work when Excel is already being open with other project/file(s).
How can I make this work?
The problem was that when you launch an Excel file in the already open Excel instance passing environment variables through cmd.exe or command line does not work correctly for some reason, rather than as a VBA-side problem.

Calling a PowerShell script from VBA in a synced location (SharePoint)

I have a working VBA script that calls a Powershell script as follows:
Call Shell("powershell -executionpolicy bypass & """ & ThisWorkbook.Path & "\FTP\FTP.ps1""")
The workbook path is H:\ABC\TSV\Forecast\Worksheets
If I move the workbook and the script to C:\Test it executes the script.
However, if I move the workbook and script to a synced location (SharePoint), it doesn't execute the script. Is the synced location's file path is too long? The file path is 72 characters (e.g. C:\Users\MyUsername\SharePointSite\SharePoint-Library\Forecast\Worksheets).
How do I get around this?
Here's a workaround:
ChDir ThisWorkbook.Path
Call Shell(ThisWorkbook.Path & "\TryShell.bat " & ThisWorkbook.Path)
TryShell.bat
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& './FTP/FTP.ps1'"

Using VBA to run WinSCP script

I am able to download files from SFTP in CMD window, by using following code:
WinSCP.com
# Connect to the host and login using password
open user:pw#address
# get all the files in the remote directory and download them to a specific local directory
lcd C:\Users\xx\Desktop
get *.xlsx
# Close and terminate the session
exit
I searched online and found out that I can put these codes in a bat file and use
Call Shell("cmd.exe /c C:\Users\xx\Desktop\WinSCPGet.bat", 1)
However, only the first line of the bat file WinSCP.com is being executed. It will pop up the cmd window, showing this, without doing anything else.
How to execute all the lines at one time?
Thanks
The code you have is not a Windows batch file. It's one Windows command followed by WinSCP commands. The first command runs winscp.com application, which then sits and waits for input. If you eventually close it, Windows command interpreter (cmd.exe) will carry on executing the remaining commands, failing most, as they are not Windows commands. See also WinSCP script not executing in batch file and WinSCP FAQ Why are some WinSCP scripting commands specified in a batch file not executed/failing?
So you either have to save the commands (open to exit) to a WinSCP script file (say script.txt) and execute the script using the /script switch:
Call Shell("C:\path\winscp.com /ini=nul /script=c:\path\script.txt")
Alternatively, specify all commands on WinSCP command line, using the /command switch:
Call Shell("C:\path\winscp.com /ini=nul /command ""open user:pw#address"" ""lcd C:\Users\xx\Desktop"" ""get *.xlsx"" ""exit""")
Regarding the quotes: With the /command switch, you have to enclose each command to double-quotes. In VBA string, to use a double-quote, you have to escape it by doubling it.
Also note that you generally should use the /ini=nul switch to isolate the WinSCP script run from your WinSCP configuration. This way you can also make sure that the script will run on other machines. Your script won't, as it lacks the -hostkey switch to verify the SSH host key fingerprint. Using the /ini=nul will help you realize that.
You can have WinSCP GUI generate complete command-line (including the -hostkey) for you.
See also Automating file transfers to SFTP server with WinSCP.
I like this small and compact procedure, and use it in my own projects. No temp-files required. Fast and reliable.
Parse a string src (an absolute filepath) to uploadImageByFTP. Etc. C:\Users\user\Desktop\image.jpg, and the file will be uploaded.
Replace:
<username> with FTP-User
<password> with FTP-Password
<hostname> with FTP-hostname (etc. example.com)
<WinSCP.com path> with path on your WinSCP-client (etc. C:\Program Files (x86)\WinSCP\WinSCP.com. Caution: WinSCP.com and not WinSCP.exe)
<FTP-path> with path on your FTP-client (etc. /httpdocs/wp-content/uploads)
Sub uploadImageByFTP(src As String)
Dim script As Object: Set script = VBA.CreateObject("WScript.Shell")
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 1
'Not empty
If (src <> vbNullString) Then
'Execute script
script.Run _
"""<WinSCP.com path>"" " + _
"/ini=nul " + _
"/command " + _
"""open ftp://<username>:<password>#<hostname>/"" " + _
"""cd <FTP-path>"" " + _
"""put " & """""" & src & """""" & """ " + _
"""close"" " + _
"""exit""", windowStyle, waitOnReturn
End If
End Sub
WScript.Shell is more powerful than the default Shell(), as you can append a waitOnReturn-command; this tells VBA, that further execution isn't allowed before the file(s) have been uploaded to the FTP-server.
Change windowStyle to 0, if you don't like the command prompt to open on each execution.

VBA Excel command doesn't work when called with Shell, but works when copy-pasted to cmd directly

I'm trying to run a program with an input file.
Dim command, cfx5_exe_path, cfx_file_folder, cfx_file_name As String
command = cfx5_exe_path & " -cfx " & cfx_file_folder & cfx_file_name & ".cfx "
Shell command
so it gives an error.
the resulting value of the command in the debugger is
"c:\"Program Files"\"ANSYS Inc"\v150\CFX\bin\cfx5pre.exe -cfx c:\Users\Username\Arbeit\Programming\A321_tail_flow.cfx"
If I copy-paste that into windows cmd directly and remove first/last quotation signs, then it works perfectly.
What is the problem with Shell?
The documentation says:
If the Shell function successfully executes the named file, it returns the task ID of the started program. The task ID is a unique number that identifies the running program. If the Shell function can't start the named program, an error occurs.
and it gives a small example:
Sub test()
Dim RetVal
Dim command As String
command = "C:\WINDOWS\CALC.EXE"
RetVal = Shell(command, 1)
End Sub
Here I get Error 53: file not found as calc on Windows 7 resides somewhere else. Do you get this error?
Providing the right path to calc starts the program and returns a unique ID.
However, quoting a part of the correct path will throw the error:
command = "C:\WINDOWS\""SYSTEM32""\CALC.EXE"
but quoting the full path does not:
command = """C:\WINDOWS\SYSTEM32\CALC.EXE"""
So you must remove all embedded quotes and then quote the full path once.

Shell command on Excel with long path name don't work

I have a batch file run.bat in a network folder "L:\Common Data\myfile" and i want to execute it from an Excel's macro.
Googling around I found these sintax:
Call Shell(Environ$("COMSPEC") & " /k L:\Common Data\myfile\run.bat", vbNormalFocus)
but it fails because it reads only "L:\Common".
I tryed many suggestion found on Internet but no one succeeded.
Someone have a solution?
Path names with spaces have to be wrapped in quotes.
Call Shell(Environ$("COMSPEC") & " /k ""L:\Common Data\myfile\run.bat""", vbNormalFocus)

Resources