using environment variables in excel - vba

So I am using this code in excel to read environment parameters on startup:
Dim ExcelArgs As String
Dim arg As String
ExcelArgs = Environ("ExcelArgs")
MsgBox ExcelArgs
If InStr(UCase(ExcelArgs), "CREO") >= 0 Then
Application.DisplayAlerts = False
If Len(ExcelArgs) > Len("CREO") Then
arg = Split(ExcelArgs, ",")(1)
Call Creo.addNewPartToPartslist(arg)
End If
Application.DisplayAlerts = True
End If
and this line in my batch script:
echo "Launch excel"
Set "ExcelArgs=CREO,DXFWITHOUTDRW
"C:\Program Files (x86)\Microsoft Office\OFFICE16\Excel.exe" /r "%APPDATA%\Microsoft\Excel\XLSTART\PERSONAL.XLSB"
exit 0
The problem is that if i run the batch file once, keep excel open change the excelargs to CREO,wqhatever in batch file and rerun batch file the excelargs, dos not get updated!!!
So my theory is that excel either caches out the environment variable or that if it is being used by one instance the batch script can not set it
link with some info about passing arguments to excel:
https://superuser.com/questions/640359/bat-file-to-open-excel-with-parameters-spaces

Usually excel sees if there is a previous instance running and let this instance handle the file opening.
Is this important? Yes, in your case both requests to open the file are handled by the same excel process.
How does it make a difference? Environment variables are not shared. Each process has it own environment block that is initialized when the process is created (can be a customized block or a copy of the environment of the parent process) and once the environment is created for a process, only this process can change its environment.
In your case, when you start excel the new process gets a copy of the environment block of the cmd process. Later, when you change the cmd environment, the already running excel instance sees no changes in environment and, as the new request to open excel is converted to a request to the previous process, there is not a new process with a new copy of the cmd environment with the changes.
The only way I see to make it work is to force excel to start a new process (that will inherit the changes in the cmd instance) instead of reusing the previous one.
But this depends on the excel version. As far as I know, the 2013 version includes an /x switch to force separate process usage. For previous versions, maybe this question, or this one could help you.

Excel is open
Then i start the batch script:
The it does not open it as read only by default, but prompt me instead, not a big issue but a bit annoying, and it also make it impossible to loop through to run the batch several times for different input parameters.
A bit unsure how I should post this, couldnt paste images in comments, and to edit the the original question, which was how to start excel with enviroment variable in new instance (/x did the trick), but now /r does not work, Should I post as new question and refer to this one or can I leave it as an answer?

Related

Environment Variables not recognized when calling Run in WScript.Shell object

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.

Setting Directories and the If Len(Dir(... statement in VBA

I have a file exists under this path:
//path/folder1/folder2/datafile.gdp
It is an input to an external program being called from vba in this manner:
Sub RunProgram()
Dim wsh As Object
SetCurrentDirectory "\\path\"
ChDir "\\path\folder1\folder2\" 'Set Directory
Set wsh = VBA.CreateObject("WScript.Shell")
check = CurDir
Statusnum = wsh.Run(Command:="program.exe ""\\path\folder1\folder2\datafile.gdp""", WindowStyle:=1, waitonreturn:=True)
But on the final line, including \path\folder1\folder2\ before the input file name appears to cause the external program to want to write some files into a duplicated directory that doesn't exist, causing an error. It used to work in this format before the .exe was updated by an external company. It now wants to write some files here, all prefixed with the name of my input file:
\\path\folder1\folder2\PATH\FOLDER1\FOLDER2\
Hoping to fix this, I changed the final line of the code to this, following some comments on a previous post here on SO:
Statusnum = wsh.Run(Command:="program.exe ""datafile.gdp""", WindowStyle:=1, waitonreturn:=True)
Since the directory is set correctly prior to calling the .exe, I thought removing the path for the input file would solve the issue.
The program now launches, but doesn't appear to load the input file with it and no longer runs calculations automatically in the background as it should. Instead, it launches and the main .exe window pops up to the user as if it had just been launched for setting up a new project, calculations don't occur automatically.
To check which directory the VBA code was try to pull my datafile.gdp from, I created these loops directly before calling the .exe:
If Len(Dir("\\path\folder1\folder2\datafile.gdp")) = 0 Then
FileIsMissing1 = True 'I use Excel-VBA watches to break if true
End If
If Len(Dir("datafile.gdp")) = 0 Then
FileIsMissing2 = True
End If
Bizarrely, neither of these loops causes a break. The file only exists in
\\path\folder1\folder2\datafile.gdp
Not in the duplicated directory... so why are both of these statements satisfied? Does entering the directory make no difference even when the current directory has been set? The current directory seems to be impacting the line:
Statusnum = wsh.Run(Command:="program.exe ""\\path\folder1\folder2\datafile.gdp""", WindowStyle:=1, waitonreturn:=True)
But not these if loops, and I'm not sure why.

Call .reg File from Excel-VBA script

I want to call a .reg File out of my VBA script. I'm using Office/Excel 2013.
I know Excel can't run these files by itself, so i need to call the file via shell. The code i wrote doesn't work:
Sub deactivateHyperlinkWarnings()
Dim x
x = Shell("cmd /C C:\TEMP\DisableHyperlinkWarnings.reg")
End Sub
I found this piece of code somewhere on the web, but its not working. I don't even get an error message. The .reg File is located in C:\TEMP
What do i need to write to make it work?
Plus: Is it possible to suppress the MessageBoxes that are displayed when i run the .reg-File? When i start the file manually, i need to Hit "OK" like 3 Times. The people who are working with the Excelsheet later on shouldn't be seeing these things.
Instead of running cmd try to run reg. So in your case it should be x = Shell("reg import C:\TEMP\DisableHyperlinkWarnings.reg")
More info here

PowerPoint 2013 macro keeps file locked open after close command

I have a PowerPoint VBA function that opens presentations, copies slides into the active presentation, then closes the source presentation. It worked fine in 2010, but fails in 2013 (all on Windows 7) if it tries to open the same presentation more than once. It appears to me that after the presentation.close command is issued, the window is closed, but the file remains locked open until the VBA code exits. So if the code attempts to open that file again it returns the error:
"Method 'Open' of object 'Presentations' failed"
Here's a simplified form of the function I'm running that behaves the same way. I've had a colleague test this again in PowerPoint 2010 and it runs fine. I've also had a colleague test it under his 2013 to make sure it's not something with my particular installation.
Sub testopen()
Dim ppFile As Presentation
Dim i As Integer
Const fpath = "C:\test.pptx"
For i = 1 To 2
Set ppFile = Application.Presentations.Open(fpath)
ppFile.Close
Set ppFile = Nothing
Next i
End Sub
The file test.pptx is just a blank presentation. In debug mode I can see the file opens and closes on the first loop, then on the second loop the open command fails and I can see in Windows explorer that the hidden temporary file still exists, indicating the file is still open, until I exit the VBA code. I also verified that the file is held open by adding in a function to check the file open status.
I've spent probably an hour googling this and cannot find any other descriptions of this problem. I'm sure I can implement a workaround but it's driving me crazy that I can't find any other reports of seemingly such a simple issue. Any suggestions are greatly appreciated! Thanks.
The Best way that I have achieved this is to simply create a VBS file and in the VBS file I call out the desired VBA code. It's little more hassle than to write the VBA code, but it's the solution that worked for me.
For example in the VBS file:
Dim args, objPP
Set args = WScript.Arguments
Set objPP = CreateObject("Powerpoint.Application")
objPP.Open "C:\path\to\file.ppx"
objPP.Visible = True
objPP.Run "The_Macro"
objPP.Save
objPP.Close(0)
objPP.Quit
Or better yet, have the entire code within the VBS file and have it copy the desired slides.
Hope this helps you achieve your result.
Setting the file as Read Only resolved the issue. The open command is now:
Set ppFile = Application.Presentations.Open(fpath, msoTrue)
Also, saving the file before closing it resolved the issue. For that, add:
ppFile.Save
Interestingly, I had already tried setting the Saved property to True (ppFile.Saved = msoTrue), which does NOT work. Thanks to Michael for his suggestion on the VBS script. That does work and I had never run an external VBS script so I learned something new. In this case, I'd prefer to stick with a VBA solution.

How can I use VB.NET to execute a batch file on another computer?

In vb.net 2008 I want to execute a batch file that resides on another computer.
There is no error, but nothing happens.
Here is the code:
Dim pStart As New System.Diagnostics.Process
Dim startInfo As New System.Diagnostics.ProcessStartInfo(serverpath & "\file.bat")
startInfo.RedirectStandardOutput = True
startInfo.WindowStyle = ProcessWindowStyle.Hidden
startInfo.UseShellExecute = False
pStart = System.Diagnostics.Process.Start(startInfo)
pStart.WaitForExit()
pStart.Close()
To run a process on a remote computer you can use Sysinternals free psexec.
You can call it with the proper parameters and having the required permissions like you are doing in your sample code.
I've never tried to create a Process using a batch file as the executable. I've always had to use cmd.exe as the program. This has worked for me in the past:
Dim startInfo As New System.Diagnostics.ProcessStartInfo("cmd.exe", "/c " & serverpath & "\file.bat")
The "/c" as part of the argument list tells cmd.exe to exit after the batch file has completed.
If you are going to use RedirectStandardOutput, you really do want to use RedirectStandardError, and then also subscribe to the events of the Process class for catching data on those streams (OutputDataReceived and ErrorDataReceived). Otherwise you will have no way to debug your batch script.
This reads like a permissions problem. I would troubleshoot it that way if you haven't ruled it out yet.
Have you tried running the same batch file from the local computer?
If it is a permissions issue you can solve it either copying the file locally before executing it or map a drive to the remote computer where the file is and then execute the batch file from the new path.
Additionally, we don't really know what's in the batch file that could be causing an issue. I would either post the batch file or if you can't post the batch file use a batch file that you can post. Example a batch file would write the current date time to a file.