Executing VB script from Spring Boot Application - excel

I want to execute a VB script from Spring Boot application, the script is like:
' Creating a file as test acces to macro
Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.CreateTextFile("C:\excel\FLAG_TEST")
Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Open("C:\excel\excelFile.xls")
objExcel.Application.EnableEvents = False
objExcel.Application.DisplayAlerts = False
objExcel.Application.Run "excelFile.xls!executeMacroFunction"
objExcel.Application.Quit
I tried to execute the script from Spring Boot service by:
Runtime.getRuntime().exec(new String[]{"C:\\Windows\\System32\\wscript.exe", "C:/vb/script.vbs"});
The above line code does not work on the application deployed on Tomcat 9 (it works fine when running as Spring Boot App on Eclipse)
Then I tried to execute the script via a batch file launched from the app
On batch file, I tried to execute the VB script by
rem First way
Set wscript = CreateObject("WScript.Shell")
wscript.Run "C:/vb/script.vbs"
--------------------
rem Second way (System 64bit)
C:\Windows\System32\wscript.exe C:/vb/script.vbs
--------------------
rem Third way (System 64bit)
wscript C:/vb/script.vbs
And running the batch file from Java with different ways too:
// First way
ProcessBuilder processBuilder = new ProcessBuilder("C:/batch/executor.bat");
final Process process = processBuilder.start();
// Second way
Process process = Runtime.getRuntime().exec("cmd /c start \"\" C:/batch/executor.bat");
// Third way
Process process = Runtime.getRuntime().exec(
"cmd /c start \"\" C:/batch/executor.bat",
null,
new File("C:\\Windows\\SysWOW64"));
All these ways do not work, the scripts have no problem since they work when I run manually the batch file (by double click)
On the execution of the macro from Spring Boot, the test file (FLAG_TEST) is created and then the execution is blocked at the line:
Set objExcel = CreateObject("Excel.Application")
Am I missing something ?...Thanks a lot in advance !

Tried also with Jacob DLL to run the Macro inside the excel file, it also didn't work for me within a Tomcat server
I decided at the end to abandon any kind of external tool and do the thing within Spring Boot, parsing the Excel file via an Excel Java API and migrating the Macro program to Java: JExcel
<dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6.12</version>
</dependency>
Unlike some other Excel parsing APIs, the Jexcel get the cell text as it is: String, Number, Boolean, Formula (its displayed result), no need to handle the different cases of content type
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;
import jxl.WorkbookSettings;
// Set Encoding 1252 that supports many European languages (special characters included)
WorkbookSettings workbookSettings = new WorkbookSettings();
workbookSettings.setEncoding("Cp1252");
Workbook workbook = Workbook.getWorkbook(new File(EXCEL_FILE_LOCATION), workbookSettings);
Sheet sheet = workbook.getSheet(0);
Cell cellDemo = sheet.getCell(0, 0); // Or sheet.getCell("A1");
// Get the displayed cell centent as a text
String cellContent = cellDemo.getContents();
System.out.print("Cell A1 centent:" + cellContent);
The Java parsing makes the exception handling of data validation easier and more precise, no kind of abstract HMI error message (Error occurred wile processing the Excel file...)
Turns out that the Excel Java reading API implementation took less time than the several attempts of runing the Macro externally :D

Related

VBA print console output when running script with exec

I wish I could run a vba script (which calls a python script) without using WaitOnReturn (so it keeps my Excel unblocked) and displaying stdout in real time in a console.
I run the script from Excel 365 on a Windows machine.
I know I can launch script using Run or Exec. As I didn't want to block Excel, I use here Exec.
But I don't manage to display outputs from the script in the console Excel opens.
Any help please ?
Here's my code :
Set wsh = VBA.CreateObject("WScript.Shell")
Dim obj_exec: Set obj_exec = wsh.exec("foo")
While obj_exec.Status = 0
Debug.Print obj_exec.StdOut.ReadLine()
Wend
I was hoping Debug.Print would work ...

Why isn't my script able to locate my excel file when given correct filepath?

I have a .vbs script that opens two excel files and copies the contents of a sheet from the first file into the second file. It's supposed to run daily via task scheduler.
The script ran normally until the excel files in question were recently modified and slightly renamed - I went through the script and edited the filenames accordingly after the changes were made, triple checking that the names and filepaths matched up.
Everything ran fine for a few weeks after the changes but now the script fails immediately after starting, giving me an error claiming that the file can't be located even though the file is located at the given path. The error code is 800A03EC.
This is the first chunk of code in the script, including line 7 which seems to be throwing the error:
Dim objApp ' as excel object
Dim x, y ' as workbook
Set objApp = CreateObject("Excel.Application")
objApp.DisplayAlerts = False
objApp.Visible = False
Set x = objApp.Workbooks.Open("S:\Work (Public)\PORT MGMT & TRADING\PORT MGMT FORMS\ORION_FPFOCUS.xlsm")
Set y = objApp.Workbooks.Open("S:\Work (Public)\PORT MGMT & TRADING\PORT MGMT FORMS\FPFocusPasteSpecialValues.xlsb")
Dim WSx, WSy ' as excel worksheet
Set WSx = x.Worksheets("FPSUP")
Set WSy = y.Worksheets("FPFOCUS-COPY")
WSy.Range("B1").value = FormatDateTime(Now)
objApp.Application.Run "ORION_FPFOCUS.xlsm!Auto_Open"
The excel files in question are both located in the same directory:
S:\Work (Public)\PORT MGMT & TRADING\PORT MGMT FORMS\ORION_FPFOCUS.xlsm
S:\Work (Public)\PORT MGMT & TRADING\PORT MGMT FORMS\FPFocusPasteSpecialValues.xlsb
And the script is located here:
C:\Users\bserv\Documents\CopyFPFocus.vbs
The S drive isn't a physical drive, it's a virtual drive hosted by a service called Workplace. I can navigate through it and open the excel files manually just fine.
I initially thought it was a user privilege issue with task scheduler, but I've selected the 'run with highest privileges' option and the script is still failing. I also went through the privacy/trust settings in Excel to make sure the script wasn't being denied access, but I don't see any settings that would disable the script from working, and I also know that all these settings haven't changed since the script was working, so I don't see how they could be potential causes.
When I try running the code manually via cscript in the command line, it returns this error:
C:\Users\bserv\Documents\CopyFPFocus.vbs(25, 4) (null): The remote procedure call failed.
This is line 25 of the script for reference:
objApp.Run "RefreshAllStaticData"
When I try again by running command prompt as an admin, I get the same error I got initially. Sorry, is it possible the file was moved renamed or deleted.
The part that really confuses me is that the script ran fine for some time after the changes - so I'm really unsure about what actually changed to cause this issue to randomly pop up.
One other thing I've noticed is that upon opening the excel files I get a popup saying they're in use and locked for editing by me. I can't remember if this popup was showing up before the issue started. The other users on the network have been accessing these files regularly long before the script started failing, so I don't see how that could be the issue. The error code/message also doesn't seem to correspond with this being the problem.
I'd appreciate any help or insight into this issue. Thank you!

Using functional application ID could not create object for WScript.CreateObject("Excel.Application")

Maestro runs with functional application ID and calls a Powershell script file
The PS script file calls a batch file - Run.bat
The batch file calls a Windows Script file (cscript.exe ...xxx.wsf)
The WSF runs a VBS program
It calls an Excel macro.
But the VBS program fails in the step where it tries to create Excel object and fails with the message "Could not create an object named excel.Application".
This script is working when user manually executes run.bat file.
Maestro also is working when functional application id credentials were used to login the server while maestro runs Run.batch file.
Please help why maestro could not create excel object in non-interactive mode i.e. user who runs the process is not actively logged in to the server.
Code in run.bat file:
cscript.exe ..\..\run.wsf
Code in run.wsf file:
<script language="vbscript" src="..\Run.vbs"></script>
Code in run.vbs file:
Dim xlApp, xlBook
Set xlApp = WScript.CreateObject("Excel.Application") -- Program fails here
Set xlBook = xlApp.Workbooks.Open(fnGetAbsolutePath(xlsFile))
I found the problem. Excel dcom-identity settings had been set as "interactive user" in that server which caused non-interactive excel requests run using interactive user's id. When I changed the setting below, it worked.
1: start->run and type 'DCOMCNFG'
2: Open 'DCOM Config' and locate 'Microsoft Excel Application'
3: Set its identity to 'The Launching User'.

Excel VBA: Can Shell run a macro in a workbook in another Excel instance

For example something like this to open the workbook in a new instance and then start the macro:
Shell(Excel.exe workbook.xlsm!macro1)
Or if the workbook was already open then:
Shell(xlObject macro1)
Most important thing is to use Shell so as to allow the code to continue whilst the macro runs separately. If not possible then perhaps I could Shell(file.bat) to a batch file that would do the same. What would the batch file look like?
Thank you.
You cannot execute VBA code inside a host application from the command line - that includes Shell.
There are two alternatives, though (with Excel#1 being the current open file and Excel#2 being the one you want to run the code in):
Put the code you want to run in the Excel #2 workbook's Workbook_Open event handler so it will execute every time you open that file - independet of how it was opened.
Have Excel#1 create a new Excel.Application object in VBA and open Excel#2 in that application. You could now call the Run() method on the Excel#2's application object to execute code from Excel#2, but this will be done synchronous to the Excel#1's code. You can use the Excel#2 application's OnTime() method though for delayed macro execution, in which case Excel#2's application will call the code when the delay has passed and the code runs asynchronous in Excel#2's application.
Sample code for Option 2 could look like this:
Public Function RemoteRun(ByVal strFile As String) As Application
Dim app As Application
Dim wb As Workbook
Set app = New Application
Set wb = app.Workbooks.Open(strFile)
app.OnTime Now + 1 / 24 / 60 / 60, "RemoteMacro"
Set RemoteRun = app
End Function
Make sure to store the return value (the Excel#2's application object) somehwere so it won't automatically close (it still has to run RemoteMacro asynchronously). Setting its Visible property to True will work as well if you don't want Excel#1's code to manage the lifetime of Excel#2's application object.

WSH Jscript AppActivate() and Sleep()

I'm trying to learn JScript (not javascript) but I'm having a hell of a time finding resources. What I want to do is manipulate the windows shell to create a program that manipulates other programs so I specifically need to be able to use Jscript's AppActivate() function to switch focus between windows however it doesn't work. I'm assuming it doesn't work because the calls to AppActivate are happening before the windows I'm trying to manipulate fully load?
Could someone please:
Give me a working example of switching between say, calculator and notepad, also give me some good reference material?
Also, how do I pause the program at the end of execution so I can read the errors in the command prompt?
This is what I wrote, and it crashes every time.
import System;
import System.Drawing;
import System.Windows.Forms;
import Accessibility;
//Open calculator, wait 3 seconds, open notepad, wait three seconds, change focus to calculator.
var WshShell = new ActiveXObject("WScript.Shell");
WshShell.Run("calc");
WshShell.Sleep(3000);
WshShell.Run("c:/windows/system32/notepad.exe");
WshShell.Sleep(3000);
AppActivate("calc");
The first lines of your script (import ...) aren't WSH JScript. Delete them. The WScript.Shell object doesn't have a .Sleep method. That method is provided by the (global) WScript object. To use .AppActivate, you need to specify the WScript.Shell object.
Working code:
var WshShell = new ActiveXObject("WScript.Shell");
WshShell.Run("calc");
WScript.Sleep(3000);
WshShell.Run("c:/windows/system32/notepad.exe");
WScript.Sleep(3000);
WshShell.AppActivate("calc");
To see what's going on, start your script from a console ('DOS box').
Start reading here.
Update wrt comments:
WSH JScript is not .NET JScript. A 'port' of the above script to .NET looks like:
import System;
var WshShell = new ActiveXObject("WScript.Shell");
WshShell.Run("calc");
System.Threading.Thread.Sleep(3000);
WshShell.Run("c:/windows/system32/notepad.exe");
System.Threading.Thread.Sleep(3000);
WshShell.AppActivate("calc");
System.Threading.Thread.Sleep(3000);
WshShell.AppActivate("notepad");
As you can see, you need to use the sleep feature of the platform (WSH vs .NET).

Resources