I'm currently using VBA (Excel) to call the FTP Shell to grab files from a directory. I want to grab all files in the directory that do not contain the wildcard %payment%, but I'm not sure of the syntax.
Sub executeFTPBatch()
Call Shell("FTP -i -s:C:\temp\ftp_directions.txt")
End Sub
So my text file opens the FTP server, inputs the user/pw and then selects the directory. I just need the command to put into the text file. Something like
mget *. * where filename != %payment% "c:\temp\" "ftp://currentfolder"
Any help would be greatly appreciated!
I'm not sure, what is "wildcard %payment%".
Though the built-in Windows ftp.exe does not support negative masks in any way.
I can suggest these solutions:
Run the ftp.exe once to get a directory listing (the ls command); parse the listing in your VBA code; select the files you want; and dynamically generate another ftp script to download these files.
Use another command-line FTP client, that supports negative masks.
For example with WinSCP scripting you can do:
Call Shell( _
"C:\path\WinSCP.com /log=C:\path\excel.log /command " & _
"""open ftp://user:password#example.com/"" " & _
"""get /path/* C:\path\ -filemask=|*%payment%*"" " & _
"""exit""")
To ease reading, the above runs these WinSCP commands:
open ftp://user:password#example.com/
get /path/* C:\path\ -filemask=|*%payment%*
exit
If you prefer, you can put the commands to a script file and run the script with the /script= command-line parameter, similarly to the ftp -s:, instead of the /command.
See the guide to Converting Windows FTP script to WinSCP script.
See also WinSCP file mask reference.
Alternatively you can use WinSCP .NET assembly via COM from the VBA code.
(I'm the author of WinSCP)
Related
If I run the command Rscript "C:/TEMP/test.R" in the command line it works and my script runs as expected. Once I try to run it in my VBA code it does not recognize the Rscript as a valid command.
Dim shell_obj As Object
Set shell_obj = VBA.CreateObject("WScript.Shell")
Dim errorCode As Integer
errorCode = shell_obj.Run("Rscript ""C:/TEMP/test.R""", 1, True)
When I looked into the PATH variable being used by the WScript.Shell I saw that it does not include the System Variables with the Rscript path inside of it.
Dim shell_obj As Object
Dim wshSystemEnv As Object
Set shell_obj = VBA.CreateObject("WScript.Shell")
' This one does not include the path to the Rscript'
Debug.Print shell_obj.ExpandEnvironmentStrings("%PATH%")
Set wshSystemEnv = shell_obj.Environment("SYSTEM")
' This one includes the path to the Rscript'
Debug.Print wshSystemEnv("PATH")
Can I force the the WScript.Shell object to use the System environment? Or at least use its variables?
Cmd:
VBA (version 1):
VBA (version 2):
EDIT: See bottom of post.
Hopefully you'll find some use in my (lengthy) take on this... :-)
Testing for command-line readiness
Any command (including an RScript) that can be run as-is from the Windows command-line can also be run with either the VBA Shell function or the Windows WScript.Shell method.
The issue is, your cmd string is not command-line ready. This can be confirmed by hitting +R and pasting the contents of your cmd string variable:
Rscript "**path**/test.R"
I don't currently have rscript.exe installed but I suspect you will get an error if you try running your command manually in either the Run window or on the command line. If it doesn't run there it obviously won't run with in a VBA Shell.
As I understand it, the double asterisk is a Java notation the way you are using it, and in R is the same as a ^ caret character, which is for calculating exponents.
Referencing an environment variable
To return the Windows PATH environment variable in VBA, you would use VBA's Environ function.
To insert the value environment variable inline at the command line, you would surround it with %percent% symbols, like %path%
Windows' PATH environment variable
PATH does not return a single folder. It's a list of folders that Windows should check to find an executable file that one attempts to run.
When a command is entered in a command shell or a system call is made by a program to execute a program, the system first searches the current working directory and then searches the path, examining each directory from left to right, looking for an executable filename that matches the command name given.
The Windows system directory (typically C:\WINDOWS\system32) is typically the first directory in the path, followed by many (but not all) of the directories for installed software packages.
An example a default value of PATH (from a fresh install of Windows 7) is:
%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem
As with %path%, this includes%SystemRoot%` which, by default on Windows 7 is the string:
C:\Windows
Checking environment variables
You can verify the value of your PATH environment label:
Hit +R.
Type cmd and hit Enter. (A command line window should open.)
Type or paste echo %path% and hit Enter.
The contents of the Window PATH environment variable will be displayed.
You can also check environment variables from within Windows:
and type env (to search)
Click Edit the system environment variables. (There is a similar option "...for your account" which is not quite the same.)
Click
Note: Although you technically can change the PATH in this window, I would not recommend doing so, especially with PATH since it is split up into System and User folders, and Windows likes certain folders in certain areas, and some changes don't take effect until reboot but others do, and blah blah blah, trust me: it's easier to do from the command line.
What's wrong with your code?
Therefore it based on all of this, it appears that the command you're trying to run is:
Rscript "C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem/test.R"
...which obviously will not work.
Get or set the current working folder/directory
I can only speculate as to what you're trying to accomplish.
I suspect you didn't intend to return the entire PATH variable, but are only interested in the current working folder.
If so, you don't need to specify a folder at all. Shell already commands execute in the "current" folder.
One way you can check which directory or folder is current, is with the VBA CurDir() function, like:
Debug.Print CurDir()
The value of CurDir can be changed with the ChDir statement.
Similar functions
Note that the CurDur() command is often confused with similar functions like:
Application.Path which returns the path to the Excel application, or,
ActiveWorkbook.Path which returns the location that the active workbook is saved (or an empty string if it's unsaved).
Possible Solution: (How to run an rScript in the current path in VBA)
If your R script and the rscript.exe are both in the current working folder, run it with just one line of VBA:
Shell "rscript.exe test.R", vbNormalFocus
If you require VBA to wait for execution of the Shell command to complete before resuming VBA, then you can you just this one line:
CreateObject("WScript.Shell").Run "rscript.exe test.R", vbNormalFocus, True
More Information:
I generally make a point of including links to any sites I used to verify my answers, so this must be my most-researched answer yet because I've never had a list this long... and I left some off out this time!
Stack Overflow : Running R scripts from VBA
MSDN : Shell Function (VBA)
MSDN : Environ Function (VBA)
R-Bloggers : Passing arguments to an R script from command lines
Stack Overflow : R.exe, Rcmd.exe, Rscript.exe and Rterm.exe: what's the difference?
Stack Exchange: Statistics : Double star ** in R?
Wikipedia : PATH (variable)
Stack Overflow : Default values of PATH variable in Windows 10
SuperUser : Default PATH for Windows 7
MSDN : CurDir() Function (VBA)
MSDN : ChDir() Statement (VBA)
MSDN : Application.Path (Excel/VBA)
MSDN : ActiveWorkbook.Path (Excel/VBA)
Stack Overflow : Wait for Shell command to complete
MSDN Forums : Difference between wscript.shell and shell.application
Stack Overflow : Steps to run R script through Windows command prompt
One More Demo of What's Wrong With Your Code:
I have a batch file named test.bat located in C:\WINDOWS. My PATH environment variable contains C:\WINDOWS (among other things).
If I go to the command prompt in root folder C:\ and type test.bat:
...it runs properly (even though my file is not in that folder... since the c:\windows folder is within the PATH variable.)
However, if I go to the command prompt and type C:\test.bat:
...it does not work. It cannot find the file because I specified a folder where the file is not located.
--- In VBA, if I run the command Shell "test.bat",1:
...it runs properly (even though my file is not in that folder... since the c:\windows folder is within the PATH variable.)
However, if in VBA I run the command Shell "c:\test.bat",1:
...it does not work. It cannot find the file because Ispecified* a folder where the file is not located**.
Both VBA and the Shell command are behaving the same way, when given the same information.
If you have recently modified the system PATH variable, you must restart the Office application you are running VBA from. VBA sends WScript the path variable and only rereads it on a restart. On restart, it will reread the PATH variable from the system and send the new correct path to WScript.
I had the same issue. I had updated the system PATH variable, but the WScript.Shell object was being passed the path variable from Excel rather than reading from the system. Excel had read the path at startup and was not aware it had changed. Once I closed Excel and reopened, WScript had the updated path variable and my script execute successfully.
I have been attempting to automate a series of administrative events for some of the users where I work by creating scripts and macro's and so on..
These scripts and macros work great, however, I would like to make a the process even easier for the users by running a single batch file that will systematically execute the scripts and macros.
The batch file I currently have, calls all the scripts one by one, and the very last script opens one of the xlsm workbooks which contains a few macro's in it - and here is where the issue is - There are still scripts to be executed but they can only be executed once this workbook has executed all its macros.
So my initial thought was to test if the workbook is open, if it is, delay the execution of the next script by a minute or so, then test again and again... until it is closed.. Then I thought perhaps it would be easier to execute the next set of scripts (also in a batch file) from within a macro.
So, I have this code:
Sub Run_BAT()
Set obj = CreateObject("Wscript.Shell")
obj.Run Chr(34) & "X:\Test\" & "Termination Reports Scripts\" & "Execute_Terminations.bat" & Chr(34), 0, True
Set obj = Nothing
End Sub
Which gives me an error:
Permission Denied
Then there's this code:
Sub WriteAndRunBatFile()
Call Shell("X:\Test\Termination Reports Scripts\Execute_Terminations.bat")
End Sub
Which gives me the error:
Invalid procedure call
Any and every single code sample that contains the "Shell" command gives this error.
Place your path to bat file in quotes:
Call Shell("cmd /c ""S:/somebatfile.bat""", vbNormalFocus)
Or
Call Shell("cmd.exe /C /K " & "ChDir X:\Test\Termination_Reports_Scripts && Execute_Terminations.bat", vbNormalFocus)
And yes, check permissions.
My theory is you're missing a reference in your application to the Windows Script Host Object Model.
In the VBA Editor, go to Tools, References, make sure that one's ticked.
It's not ticked by default for security reasons - imagine unintended access to the command prompt in every instance of a Microsoft Office application...!
(1) Check permission of user of that X directory.
(2) Test the code by removing spaces from directory name.
Also try the following code (Please try it by removing spaces from directory name).
Sub Button1_Click()
Call Shell("CMD.EXE /C " & "X:\Test\Termination_Reports_Scripts\Execute_Terminations.bat")
End Sub
When I click directly in the .exe file "PrintUsers.exe", the output is correct.
But when I do that through VBA using Shell the result is different. It tries to find the text file in another directory. Why? See figure:
SOLUTION: I am now using: GetModuleFileName(NULL, szEXEPath, 2048) instead of GetCurrentDir(buff, FILENAME_MAX);
It appears that PrintUsers.exe expects to find the file doNotEdit.txt in the current directory.
The best solution is to change that program to look for the file in the same directory as the program itself is located but, if that is not possible, get Excel to change the current directory before running the program, i.e. insert
ChDir ActiveWorkbook.Path
prior to invoking Shell.
Also, as Yahya Hussein mentioned in a comment, spaces inside paths can cause issues. There aren't any in your specific situation but, to ensure you don't have problems in future, consider using something like
myFile = """" & ActiveWorkbook.Path & "\PrintUsers.exe"""
ChDir ActiveWorkbook.Path
Shell myFile, vbNormalFocus
SOLUTION: I am now using: GetModuleFileName(NULL, szEXEPath, 2048) instead of GetCurrentDir(buff, FILENAME_MAX);
The Preview App on the Mac lets you add keywords to a PDF file.
Is it possible to use AppleScript to read the keywords? If so, how?
The Exiftool manages keywords for many file types, including PDF. This is a free command line tool you can download. Once the tool is installed, you can use it via Terminal or, of course, via Applescript with "do shell script".
If myFile is the PDF file selected, then you can read the existing keywords with:
set myKeyWords to do shell script "/usr/local/bin/exiftool -Keywords " & quoted form of (POSIX path myFile)
if length of myKeyWords > 35 then
set myKeyWords to text 35 thru -1 of myKeyWords
end if
The result of the command is empty (if no keywords) or it is made of 33 spaces, ':', 1 space, and the list of keywords separated by ','. This is why I added the 'if' statement after the do shell script command.
And you can also write new keywords (variable MyKey) in your PDF file with :
do shell script "/usr/local/bin/exiftool -Keywords+='" & MyKey & "' -Overwrite_Original " & quoted form of (POSIX path of myFile)
Exiftool can do many other things for images and PDF files. Some actions are specific to images, some to PDF, or for all file types. Please use the man page in Terminal to know more.
Preview.app supports only the generic classes / commands and has no application specific dictionary.
It might be possible with the ugly GUI scripting.
Is it possible to run website url using Shell() command? I saw someone post
Shell() can only read the executable path
But regarding to this site http://www.vb6.us/forums/general-questions/attaching-website-links-your-command-button Shell() can used to run the website url.
I have some website url inside my XML file and I tried to run them using Shell() command as my XML file also containing .exe file path. So I am running those .exe file and website url like this
Dim i As Integer, j As Integer
For i = 0 To 9
For j = 0 To 9
If MenuListBox.SelectedItem = MenuListBox(i, j, 0) Then
Shell(MenuListBox(i, j, 1))
End If
Next
Next
I am using array to store each of elements inside my XML file.
So the problem here is, I can only run my .exe files and when running website url it said that
File not found
Even though my path is correct. I did used the Process.Start() also but it only working for the website url, not the .exe file. It returns me this error.
The system cannot find the file specified
Kindly to help me. Thanks in advance.
Process.Start() can be used for url and executables and other files. If you pass a path to a file, like a doc file, it is open with default application. In your case if you pass a url like "http://www.google.com" it will be opened with your default browser.
According to MSDN:
Starting a process by specifying its file name is similar to typing
the information in the Run dialog box of the Windows Start menu.
Therefore, the file name does not need to represent an executable
file. It can be of any file type for which the extension has been
associated with an application installed on the system. For example
the file name can have a .txt extension if you have associated text
files with an editor, such as Notepad, or it can have a .doc if you
have associated.doc files with a word processing tool, such as
Microsoft Word. Similarly, in the same way that the Run dialog box can
accept an executable file name with or without the .exe extension, the
.exe extension is optional in the fileName parameter. For example, you
can set the fileName parameter to either "Notepad.exe" or "Notepad".
opening a url here and here
Quick solution, to get time to check the real solution:
If path.toupper like "*.EXE"
shell path
Else
process.start (path)
End if
But if you have a Win32Exception (show us the full message) ... they used to appear on 32/64 bits issue. etc. But, as Shell is working, I think you have a Credentials issue= permissions of that folder/exe.
Place that exe on another granted location to test.
Thanks to #Capitán CavernÃcola for your suggestion.
If path.toupper like "*.EXE"
shell path
Else
process.start (path)
End if
I took your code and change the path.toupper like "*.EXE" to Path.Contains(".exe") Then
Here is my coding that working all fine now.
Dim Path As String = MenuListBox(i, j, 1)
If Path.Contains(".exe") Then
Shell(Path)
Else
Process.Start(Path)
End If
Thank you all :)