I have been trying to convert a VBA for Excel code to OpenOffice Calc (basic) and now Im having trouble accessing an external program (and it´s database) to generate an output which I will use later in my code. In other words, I give an input, call the program and later I want an output file.
In VBA:
Prog = Worksheets("Settings").Cells(2, 2) & IPRODB & " -i " & DateiAll_in
Wait = True
Set sh = CreateObject("WScript.Shell")
RetVal = sh.Run(Prog, 0, Wait)
Worksheets("Settings").Cells(2, 2) is the program's path and IPRODB is the database's path, "-i" seems to be a command to the program and DateiAll_in is the Input file (.csv) I created before in the code.
The OpenOffice basic offers the function Shell(Pathname, Windowstyle, Param, bSync) to open external programs but It would not be the same since in the "run method" in VBA I am running a macro containing the program, its´s Database and Input File. (expression.Run(MacroName, varg1,varg2, (...))
Is there any alternative to the Shell function or can I use it in the same way as I used the "run method" in VBA?
From the OpenOffice.org forums (didn't test it myself):
Dim oSvc as object
oSvc = createUnoService("com.sun.star.system.SystemShellExecute")
Rem Launch notepad
oSvc.execute(ConvertToUrl("C:\windows\notepad.exe"), "", 0)
I used the Shell function. In the first argument of the function I added all the equivalents of "Worksheets("Settings").Cells(2, 2) & IPRODB & " -i " & DateiAll_in". I substituted Worksheets("Settings").Cells(2, 2) for the direct path of the program only because it was easier. So it worked with this code below:
Shell("C:\Program Files\*******\*****\*****.exe & IPRODB & "-i" & DateiAll_in",1,,True)
Related
I'm trying to cycle through several url's to download the pdf to a local folder.
An example of the url is https://find-energy-certificate.service.gov.uk/energy-certificate/8309-9619-9729-7796-8423?print=true
This is the vb I've written so far.
Dim sveloc As String
Dim svenme As String
Dim url As String
sveloc = Application.ActiveWorkbook.Path & "\Saved EPCs"
i = 7
Do Until sh01.Cells(i, 27) = "" 'all cells in the list are populated with no gaps
url = sh01.Cells(i, 27)
svenme = sh01.Cells(i, 2)
sveloc = sveloc & "\" & svenme & ".pdf"
ThisWorkbook.FollowHyperlink (url)
'code to open and save the pdf goes here
i = i + 1
Loop
Any help gratefully received as I'm really stumped on this one.
TIA.
Inspired by KJ's answer, without error checking etc. Just wanted to illustrate how you'd use shell to automate the entire process.
sveloc = Application.ActiveWorkbook.Path & "\Saved EPCs"
edgePath = Environ$("PROGRAMFILES(X86)") & "\Microsoft\Edge\Application\msedge.exe"
With CreateObject("WScript.Shell")
i = 7
Do Until Len(sh01.Cells(i, 27)) = 0 'all cells in the list are populated with no gaps
On Error Resume Next
.Run """" & edgePath & """ --profile-directory=Default --headless -print-to-pdf=""" & sveloc & "\" & sh01.Cells(i, 2) & ".pdf" & """ """ & sh01.Cells(i, 27) & """", 1, True
On Error GoTo 0
i = i + 1
Loop
End With
No need for VBA but you can use that to alter the variables so using your example from Windows we can run the build pdf at html runtime via Edge:-
"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --profile-directory=Default --headless -print-to-pdf=C:\Users\WDAGUtilityAccount\Desktop\8309-9619-9729-7796-8423.pdf "https://find-energy-certificate.service.gov.uk/energy-certificate/8309-9619-9729-7796-8423?print=true"
and as if by magic the file is in less than a second on my desktop
There is no online pdf it is built by the browser. So it is essential to use the browser. You can remove the print header/footer with one extra switch, but cannot change orientation it will be A4 portrait in UK device.
-print-to-pdf-no-header see currently https://source.chromium.org/chromium/chromium/src/+/main:headless/app/headless_shell_switches.cc;l=60
one other switch may be of value if you only want smaller untagged files
-disable-pdf-tagging see https://source.chromium.org/chromium/chromium/src/+/main:headless/app/headless_shell_switches.cc;l=64
If you try to download without browser printing you will just get the raw HTML as needed for web page printing, thus calling browser remote print as above, will generate the desired "designed for the web" graphics copy.
curl -o test.htm https://find-energy-certificate.service.gov.uk/energy-certificate/8309-9619-9729-7796-8423?print=true
In comments the question was raised how to adapt this approach for change of browser and keeping call simple so I suggest use a cmd or bat file to make that part easier. Thus from vba call something like
Batchfile 8309-9619-9729-7796-8423
#echo off
set "browser=C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"
set "filedir=C:\Users\WDAGUtilityAccount\Desktop"
set "urlpath=https://find-energy-certificate.service.gov.uk/energy-certificate"
"%browser%" --profile-directory=Default --headless --print-to-pdf="%filedir%\%~1.pdf" -print-to-pdf-no-header "%urlpath%/%~1?print=true"
However, beware calling pdf generations too fast, add a small wait between calls, even on multithreaded CPU writing PDF's at same time often leads to disasters, due to graphics resource conflicts.
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
I am trying to write some VBA in Excel that will concatenate .csv files by executing the copy and more commands in the Windows Shell.
This code successfully creates an empty file concat_target.txt (into which the others will be concatenated):
Shell ("cmd.exe copy /b NUL " & """\\path\to\network\folder\concat_target.txt""")
However, this code does not have the intended effect of saving file_1.txt as file_1.concat_temp (skipping the header):
Shell ("cmd.exe more +1 " & """\\path\to\network\folder\file_1.txt""" & " > " & """\\path\to\network\folder\file_1.concat_temp""")
In fact, every variation of the call to more that I have tried just pops up a console (that stays open) whereas the call to copy does not. The UNC network path has cursed spaces in it.
UPDATE:
It turns out that adding the /c flag to the more command does the trick (although it seems to have no effect on the call to copy). So this code is having the desired effect:
Shell ("cmd.exe /c more +1 " & """\\path\to\network\folder\file_1.txt""" & " > " & """\\path\to\network\folder\file_1.concat_temp""")
I will post the full solution for posterity once it is finished.
I don´t know why you are using 'more', but I would use other methods:
Shell ("cmd.exe /c type ""\\path\to\network\folder\file_1.txt"" >> ""\\path\to\network\folder\file_1.concat_temp""")
Notes:
redirecting with '>' will overwrite the file, losing previous contents
redirecting with '>>' will append the file (concatenate)
no need to separate every element in your string with " & " if they are all text (but I guess you already knew this)
no need to create an empty file first.
UPDATE:
OP was using 'more' to exclude the .csv table headers, as I hadn´t understood before.
So the 'type' command won´t work in this case.
Hi I have a perfectly working bat named: start.bat
containing:
start C:\Users\*user*\Documents\*path*\hidebat.vbs
and once it is manually opened it works perfectly, meaning it opens hidebat.vbs, which opens a .bat minimized which uploads files to my cloud. Hence it's verified.
I've added
pause
to the start.bat to see what it does and when I tell excel to open the start.bat it will open cmd and display the exact command as required, but it will not execute the hidebat.vbs.
I expect that there is somehow some path constraint or environment constraint when it is run from excel that prevents it to actually reach out of that limited environment.
Within excel I have tried calling the .bat in 3 different ways with:
Dim path As String
path = Application.ActiveWorkbook.path
path = path & "\"
Dim MY_FILENAME3 As String
MY_FILENAME3 = path & "start.bat"
1.
retVal = Shell(MY_FILENAME3, vbNormalFocus)
' NOTE THE BATCH FILE WILL RUN, BUT THE CODE WILL CONTINUE TO RUN.
If retVal = 0 Then
MsgBox "An Error Occured"
Close #FileNumber
End
End If
2.
PathCrnt = ActiveWorkbook.path
Call Shell(PathCrnt & "start.bat")
3.
Dim batPath As String: batPath = path
Call Shell(Environ$("COMSPEC") & " /c " & batPath & "start.bat", vbNormalFocus)
Does anybody have any clue on why it will not execute the .bat file, or what I could do to ensure it will run correctly?
Note. I think it is because it opens the default path, so I'm gonna tell it to "cd" to the actual path where the excel is saved and where the .bat files are.
Yes that was it, the path was set to some random/standard/working/current path by command, so I had to add:
Print #FileNumber, "cd " & path
to the excel macro
so that start.bat looked like:
cd *path*
start *path*\hidebat.vbs
Hope this helps future me's.
Is it possible to include in a VB.net 2008 Project a VBScript (test.vbs) and run it if its while the processing necessary? But the main thing is it should be possible to BUILD just one .exe.
If so, can you also receive values / arguments from the VBS file?
Here is an example, although it's pointless, but it is used for unterstanding:
VB.net -> exe is running
the exe runs please_find_the_coputername.vbs
The script please_find_the_coputername.vbs -> obtained the computer name and sends this variable to VB.net
VB.Net displays the computer name via Msgbox().
Note: I know that I can read out the computer name with VB.net but this example is only for understanding my questions.
Edit:
HI #maxedev thank you for your answer.
Wow.. its nice trick.
But I want only to do this VBScript code in VB.net:
Dim strComputer
strComputer = "LP-BKR"
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
Set colComputer = objWMIService.ExecQuery ("Select * from Win32_ComputerSystem")
For Each objComputer in colComputer
Wscript.Echo "Logged-on Domain: " & objComputer.Domain
Wscript.Echo "Logged-on UserName: " & objComputer.UserName
Wscript.Echo "Logged-on ComputerName: " & objComputer.Name
Next
set objWMIService = Nothing
set colComputer = Nothing
I searched the whole day to get the same Value... but didn't find anything. That's why I decide to do that in this way. But if I think, the trick with clipboard is risky. It pushes the still clipboard text away. How can I realize it?
I'm not sure exactly what you're trying to accomplish, but you could write to a text file and then read it through vb.net - or you could do something like this post to use the clipboard to pass info ie :
VBS:
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "cmd.exe /c echo hello world | clip", 0, TRUE
VB.NET:
MessageBox.Show(Clipboard.GetText)
--shows "hello world"
One solution would be to add a reference to the MS Script Control:
http://msdn.microsoft.com/en-us/library/aa227400(v=vs.60).aspx
Using that, you can add literally add code (VBScript) with the AddCode() method then run it and get the output back. I have a tiny example here.
Windows automatically provides the information you're looking for in environment variables:
%USERNAME% -> username of the logged in user
%USERDOMAIN% -> WINS name of the domain the user is logged into
%USERDNSDOMAIN% -> FQDN of the domain the user is logged into
%COMPUTERNAME% -> hostname of the computer