I had the same problem, execute a VBA script from Java and wait until it's finished:
Runtime.getRuntime().exec(new String[]{"C:\\Windows\\System32\\wscript.exe", "C:/macro.vbs"});
The Macro contains a VBS code that is running a Macro (generateOutputFiles) inside an excel file:
Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Open("C:\excel\test.xls")
objExcel.Application.EnableEvents = False
objExcel.Application.DisplayAlerts = False
objExcel.Application.Run "test.xls!generateOutputFiles"
objExcel.ActiveWorkbook.Save
objExcel.ActiveWorkbook.Close
After a long and painful research, I have decided to create a flag on the VB script itself after the end of its main program and wait for it in Java code as follows:
In VBA:
Set objExcel = CreateObject("Excel.Application")
Set objFSO = CreateObject("Scripting.FileSystemObject")
' Delete the exesting end execution flag
endLoadingFlagPath = "C:\excel\LOADING_END_FLAG"
If (objFSO.FileExists(endLoadingFlagPath)) Then
objFSO.DeleteFile endLoadingFlagPath
End If
Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Open("C:\excel\test.xls")
objExcel.Application.EnableEvents = False
objExcel.Application.DisplayAlerts = False
objExcel.Application.Run "test.xls!generateOutputFiles"
objExcel.ActiveWorkbook.Save
objExcel.ActiveWorkbook.Close
' Create the end execution flag right after the main VB program
Set objFile = objFSO.CreateTextFile(endLoadingFlagPath)
In Java:
import java.io.File;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
public class Test {
private static final Logger logger = Logger.getLogger("SCRIPT_RUNNER");
public void executeVBScript() throws Exception {
Runtime.getRuntime().exec(new String[]{"C:\\Windows\\System32\\wscript.exe", "C:/macro.vbs"});
waitLoadingFinished();
}
private void waitLoadingFinished() throws Exception {
File endLoadingFlagFile = new File("C:\\excel\\LOADING_END_FLAG");
for(int attempt = 0; attempt < 10; attempt++) {
utilSetDelay(5);
if(endLoadingFlagFile.exists()) {
return;
}
}
throw new Exception("Timeout waiting for task");
}
private void utilSetDelay(long seconds) {
try {
TimeUnit.SECONDS.sleep(seconds);
} catch(Exception ex) {
logger.warn("Cannot sleep:" + ex.getMessage());
}
}
}
The attempt count and sleep delay can be set as parameters.