Can't close Excel App with vba in a scheduled task - vba

I have made a code in vba which works with different Workbooks and Worksheets. This code must be execute in a scheduled task. But for an unknow reason I have a problem with it :
When I execute it manually, it works fine and excel closes itself. But with my scheduled task, Excel closes all Workbooks and Worksheets but it stays open.
Here you have my code :
Set xlApp = GetObject(, "excel.application")
Set wkbMe = xlApp.ActiveWorkbook
test = False
xlApp.DisplayAlerts = False
xlApp.AskToUpdateLinks = False
'Open files
xlApp.Workbooks.Open Filename:=MarketDataPath & WbRiskedge, ReadOnly:=True
xlApp.Workbooks.Open Filename:=MarketDataPath & WbMarketData, ReadOnly:=True
Set WorksheetIncoming = xlApp.Workbooks(WbMarketData).Worksheets(wsIncoming)
Set WorksheetMarketdata = xlApp.Workbooks(WbMarketData).Worksheets(WsMarketData)
xlApp.Workbooks.Open Filename:=GTPath & WbGoodTime, ReadOnly:=True
Cells.Copy
WorksheetIncoming.Activate
Range("A1").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Workbooks(WbGoodTime).Close
WorksheetMarketdata.Calculate
Worksheets(wsMarketDataForWebsite).Calculate
Worksheets(wsMarketDataForWebsite).Activate
If test = False Then
Application.Run "MarketEnv.xlsm!subCreateCSV"
End If
Workbooks(WbMarketData).Close , False
Workbooks(WbRiskedge).Close , False
xlApp.DisplayAlerts = True
xlApp.AskToUpdateLinks = True
ThisWorkbook.Save
ThisWorkbook.Saved = True
xlApp.Quit
End Sub
I have tried different solutions found on the web but nothing work. Even if I only make :
Set xlApp = GetObject(, "excel.application")
xlApp.Quit
End Sub
my excel stays open.
Anyone can help me plz ?

Okay, this seems long winded... but here goes.
The problem you are seeing is because there can be more than one instance of the Excel Application on a machine at a given time.
When you are manually running the file, you are likely using the default behavior, which is that when you open a workbook directly it opens in your already loaded Excel Application.
This means that when you use:
Set xlApp = GetObject(, "excel.application")
It is actually returning the current Excel.Application.
However, when you load it via the scheduled task, it generates a new Excel.Application in order to handle your task. When it calls the code I quoted it ends up referencing the Excel.Application you already had open (probably).
Since your scheduled workbook is running in a different instance of Excel.Application, when you run xlApp.Quit it only quits that other Excel and not the one actually running the code.
If you want to also close your automated Excel, you will need to add Application.Quit to the end of your sub. Yes, I do mean use both xlApp.Quit AND Application.Quit.
Now technically, you could have more than one Excel Applications open when you load the new one. If you want to close all instances of Excel, the simplest way I know would be to kill all of them via a vbscript call to a program like this which terminates all processes named excel.exe. Note I did not test this on Win 7:
Dim objWMIService, objProcess, colProcess
Dim strComputer, strProcessKill, strFilePath
strComputer = "."
strProcessKill = "'excel.exe'"
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
Set colProcess = objWMIService.ExecQuery _
("Select * from Win32_Process Where Name = " & strProcessKill)
For Each objProcess In colProcess
objProcess.Terminate
Next
WScript.Quit
Edit: I just wanted to add that you can replicate the behavior of the scheduled task manually by doing the following:
Have Excel already open.
Navigate through your start menu and open Excel.
From the new instance of Excel, open your workbook.
OR
Have Excel already open.
Run the following Excel.exe [path of workbook in quotes]
Edit 2:
Due to your request, I've written this short vbscript file that will close all open Excel Applications without upsetting auto-recover. If you also want to avoid any, "Do you want to save ..." alerts uncomment the commented section.
On Error Resume Next
Dim xlApp
Set xlApp = GetObject(, "Excel.Application")
Do While Err.Number <> 429
'For each wb in xlApp.Workbooks
' wb.saved = true
'next
xlApp.Quit
Set xlApp = Nothing
Set xlApp = GetObject(, "Excel.Application")
Loop
Wscript.quit
To run it, just include the following at the end of your Excel VBA.
Shell "wscript.exe [path of .vbs file]"

I can see you have opened more than one workbook instances with your excel application. You need to close all workbook instances to get the plain excel application and than quit it.
try this: (pseudo code)
dim xlApp as Excel.Application
dim wBook as Excel.Workbook
dim wSheet as Excel.Worksheet
Set xlApp = new Excel.Application
Set wBook = xlApp.Workbooks.Add(wb_Path)
Set wSheet = wBook.Sheets(1)
wSheet.Range("A1").Value = "Hello this is a test from vbcode"
wbook.close saveChanges:= true
xlApp.quit
Above code will open your workbook. write a custom message on your worksheet
saves the changes and closes. and the xlapp will also be terminated/destroyed.

Related

Quitting Excel Workbook from Word leaves Excel open

I have a Macro in Word, that is reading data from an Excel file.
I have the following lines in my Macro to open and close the Excel file:
Excel_path = "C:\Users\....\Documents\myExcelfile.xlsx"
Dim myExcel As Object
Dim myWB As Object
Set myExcel = CreateObject("Excel.Application")
Set myWB = myExcel.Workbooks.Open(Excel_path)
With myWB.Sheets(2)
*.... Reading in data ....*
End With
myWB.Close savechanges:=False
myExcel.Quit
End Sub
Although I close both the workbook and I quit the application, I keep getting the message that my Excel file is locked for editing after succesfully running the Macro in Word. Also, if I close the Word application I keep having this..
I checked in my Excel workbook, but it doesn't show any connections.
How can I truly quit my Excel workbook?
I would Suggest you to do :
Application.Quit
For example :
myWB.Close SaveChanges:=False
With myExcel
.DisplayAlerts = False
.Quit
End With
And if after that Excel process Still exist in your process manager then use kill to kill excel process. You can found an example there.
Basicly I would do like this to be sure that Excel Is definitivly closed :
Sub Tryme()
Dim MyList As Object
Dim oServ As Object
Dim cProc As Variant
Dim oProc As Object
myWB.Close SaveChanges:=False
With myExcel
.DisplayAlerts = False
.Quit
End With
Set objList = GetObject("winmgmts:") _
.ExecQuery("select * from win32_process where name='" & process & "'")
If MyList.Count > 0 Then
Set oServ = GetObject("winmgmts:")
Set cProc = oServ.ExecQuery("Select * from Win32_Process")
For Each oProc In cProc
If oProc.Name = "EXCEL.EXE" Then
MsgBox "KILL" ' used to display a message for testing pur
oProc.Terminate()
End If
Next
End If
End Sub
Don't close the workbook, instead do:
myWB.Saved = True
myExcel.Quit
Instead of setting .Saved you can also set
myWB.DisplayAlerts = False

VBScript to loop through Excel-files and change macro

I already posted a closely related question last week VBScript to add code to Excel workbook which got solved by a fellow programmer. But I ran into the next problem with that task:
With the following code, I try to loop through a folder of Excel files then open them one by one and change the macro in DieseArbeitsmappe. This works fine for the first file but the second ends with this error message.
Error message
Set objFSO = CreateObject("Scripting.FileSystemObject")
sFolder = "P:\Administration\Reports\operativ\Tagesbericht\templates\START07\TestTabsiNeu\"
Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = True
objExcel.DisplayAlerts = False
For Each objFile In objFSO.GetFolder(sFolder).Files
Set objWorkbook = objExcel.Workbooks.Open(sFolder & objFile.Name)
Set component = objworkbook.VBProject.VBComponents("DieseArbeitsmappe")
strCode = _
"Sub WorkBook_Open() 'just for testing" & vbCr & _
" Application.Run (""'CommonMacro.xlsm'!Workbook_Open"")" & vbCr & _
"End Sub"
component.CodeModule.AddFromString strCode
objWorkbook.SaveAs "P:\Administration\Reports\operativ\Tagesbericht\templates\START07\TestTabsiNeu\" & objFile.Name
objExcel.Quit
Set objWorkbook = Nothing
Set component = Nothing
Next
Set objFSO = Nothing
Set objExcel = Nothing
Line 10 is Set component = objworkbook.VBProject.VBComponents("DieseArbeitsmappe")
Another problem I will face soon is that sometimes the VBComponent is called ThisWorkbook. So I will have to introduce if-else based on the Error code thrown by Line 10. Or is there a better solution for this?
Thanks in advance for your help.
This isn't a perfect answer, as I am more confused than I am certain of the exact problem... However hopefully this will help.
The command objExcel.Quit is going to close the Excel application.
I'm not quite sure how the code (in the next loop) then successfully executes
Set objWorkbook = objExcel.Workbooks.Open(sFolder & objFile.Name)
when the objExcel application has been quit. However, the .Visible and .DisplayAlerts will no longer be set True/False. The latter could cause your failure in line 10.
Therefore I suggest replacing
objExcel.Quit
with
objWorkbook.Close

Ignore "Do you wish to save" box on exit of excel

I have a script that opens an excel file and runs a macro, then quits the file. Since the file is in read only mode, and the script makes temporary changes to the file, when the script calls myExcelWorker.Quit() excel asks if I want to save my changes and I must click 'no'. Is there any way to exit the program and skip this box?
' Create a WshShell to get the current directory
Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
' Create an Excel instance
Dim myExcelWorker
Set myExcelWorker = CreateObject("Excel.Application")
myExcelWorker.Visible = True
' Tell Excel what the current working directory is
' (otherwise it can't find the files)
Dim strSaveDefaultPath
Dim strPath
strSaveDefaultPath = myExcelWorker.DefaultFilePath
strPath = WshShell.CurrentDirectory
myExcelWorker.DefaultFilePath = strPath
' Open the Workbook specified on the command-line
Dim oWorkBook
Dim strWorkerWB
strWorkerWB = strPath & "\BugHistogram_v2.xlsm"
Set oWorkBook = myExcelWorker.Workbooks.Open(strWorkerWB)
' Build the macro name with the full path to the workbook
Dim strMacroName
strMacroName = "CreateImagesButton_Click"
on error resume next
' Run the calculation macro
myExcelWorker.Run strMacroName
if err.number <> 0 Then
' Error occurred - just close it down.
End If
err.clear
on error goto 0
' oWorkBook.Save ' this is ignored because it's read only
myExcelWorker.DefaultFilePath = strSaveDefaultPath
' Clean up and shut down
Set oWorkBook = Nothing
' Don’t Quit() Excel if there are other Excel instances
' running, Quit() will
' shut those down also
if myExcelWorker.Workbooks.Count = 0 Then
myExcelWorker.Quit
End If
myExcelWorker.Quit()
Set myExcelWorker = Nothing
Set WshShell = Nothing
ActiveWorkbook.Close False (to close the workbook)
Application.Quit (to quit Excel - doesn't prompt to save changes)
From Microsoft Support's How to suppress "Save Changes" prompt when you close a workbook in Excel:
To force a workbook to close without saving any changes, type the
following code in a Visual Basic module of that workbook:
Sub Auto_Close()
ThisWorkbook.Saved = True
End Sub
Because the Saved property is set to True, Excel responds as though the workbook has already been saved and no changes have
occurred since that last save.
The DisplayAlerts property of the program can be used for the same
purpose. For example, the following macro turns DisplayAlerts off,
closes the active workbook without saving changes, and then turns
DisplayAlerts on again.
Sub CloseBook()
Application.DisplayAlerts = False
ActiveWorkbook.Close
Application.DisplayAlerts = True
End Sub
You can also use the SaveChanges argument of the Close method.
The following macro closes the workbook without saving changes:
Sub CloseBook2()
ActiveWorkbook.Close savechanges:=False
End Sub
The answer you have above is for VBA - you can address this in your VBS directly by using
oWorkBook.Close False
Set oWorkBook = Nothing
in place of
Set oWorkBook = Nothing

Workbooks.Open returns different file than Filename

I am having the strangest problem. I was writing the below code on my laptop the other day and it worked fine. Now, I am testing it on my desktop and it's stopped working.
First, here's my code
Dim oApp As Application
Dim oWb As Workbook
Set oApp = New Application
oApp.Visible = True
Set oWb = oApp.Workbooks.Open(Filename:="C:\myFile.xlsx", ReadOnly:=True)
debug.print oWb.name
'returns "SOLVER.XLAM"
' "SOLVER.XLAM" is not "myFile.xlsx'
debug.print oApp.Workbooks.Count
'returns 1
debug.print oApp.Workbooks(1).name
'returns "myFile.xlsx"
Now, I know that solver is an add in, and it gets loaded in the new application upon creating it... but how does it perform this switcheroo? I can still get to the correct file, but I don't want to risk it on the coincidence that there is only 1 file in my Application object (or that the first file is the one I loaded)
Additional Info
I am calling executing this macro from within an excel instance and I wish to open a separate excel instance and then open particular workbook ("C:\myFile.xlsx") inside that other instance.
The key problem I'm having is that when I open the other instance and then add the workbook and set it to my oWb variable... somehow, when I later call that oWb variable it refers to something different from what I had set it to.
'This is how it makes me feel:
Dim x As Integer
x = 5
Debug.Print x
' 12
I think if you just refine your code a bit to ensure you are doing exactly what you want, you will be fine. Since it's unclear whether you are calling the code from within Excel or another MS Office Application, I placed to subs below.
Run this if running it in Excel:
Option Explicit
Sub insideXL()
Dim oWb As Workbook
Set oWb = Workbooks.Open("C:\myFile.xlsx", ReadOnly:=True)
Debug.Print oWb.Name
Debug.Print Workbooks.Count
Debug.Print Workbooks(1).Name
oWb.Close false
Set oWb = Nothing
End Sub
Run this if running in another program. I use early binding, but you could use late binding as well, if you wish:
Sub outsideXL()
'make sure Microsoft Excel X.X Object Library is checked in Tools > References
Dim oApp As Excel.Application
Set oApp = New Excel.Application
Dim oWb As Excel.Workbook
Set oWb = oApp.Workbooks.Open("C:\myFile.xlsx", ReadOnly:=True)
oApp.Visible = True
Debug.Print oWb.Name
Debug.Print Workbooks.Count
Debug.Print Workbooks(1).Name
oWb.Close = True
Set oWb = Nothing
Set oApp = Nothing
End Sub
I found that this (which worked in 2007):
wb = excel.Workbooks.Open(filename, False, True)
needs to be written
excel.Workbooks.Open(filename, False, True)
wb = excel.ActiveWorkbook
for 2010

Macro gets disabled if called using a vb script

I am trying to call my excel macro using vbs. Here is a snippet of my code.
Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Open("C:\Folder\Test_PO.xls")
objExcel.Application.Visible = True
objExcel.Application.Run "C:\Folder\Test_PO.xls!Data_Analysis"
objExcel.ActiveWorkbook.Close
objExcel.Application.Quit
WScript.Echo "Finished."
WScript.Quit
Now the problem here is that i am able to open the file but the macro somehow gets disabled here and shows me 'macro may not be present or may be disabled'. I am sure i am calling correct macro name but as soon as the file is opened the Add-ins tab where i had configured the macro to run from gets dissapeared.This does not open if i open the file manually , i can see the tab and run the macro from the tab itself. Any suggestions how i could overcome this problem and get the macro to run ?
Try this
Dim objExcel, objWorkbook
Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Open("C:\Folder\Test_PO.xls")
objExcel.Visible = True
objExcel.Run "Data_Analysis"
objWorkbook.Close
objExcel.Quit
Set objWorkbook = Nothing
Set objExcel = Nothing
WScript.Echo "Finished."
WScript.Quit
EDIT
If the macro is in a module then the above will help. If the macro is in a sheet say, Sheet1 then replace the line
objExcel.Run "Data_Analysis"
with
objExcel.Run "sheet1.Data_Analysis"
FOLLOWUP
Try this code.
Dim objExcel, objWorkbook, ad, FilePath
Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = True
For Each ad In objExcel.AddIns
If ad.Name = "Converteam.xla" Then
FilePath = ad.Path & "\Converteam.xla"
Exit For
End If
Next
objExcel.Workbooks.Open (FilePath)
Set objWorkbook = objExcel.Workbooks.Open("C:\Folder\Test_PO.xls")
objExcel.Run "Data_Analysis_Converteam"
objWorkbook.Close
objExcel.Quit
Set objWorkbook = Nothing
Set objExcel = Nothing
WScript.Echo "Finished."
WScript.Quit
EXPLANATION:
When you use CreateObject, the Add-Ins are not installed by default. Please see this link.
Topic: Add-ins do not load when using the CreateObject command in Excel
Link: http://support.microsoft.com/kb/213489/
You have to load the Add-In and then call the relevant macro. Also the name of your macro is not Data_Analysis but Data_Analysis_Converteam
HTH
To add to Siddhart's answer - you can load the addins you require in a VBScript like this:
objExcel.RegisterXLL("analys32.xll") 'For XLL addins
objExcel.Workbooks.Open(objExcel.LibraryPath & "\analysis\atpvbaen.xla") 'For standard XLA addins
objExcel.Workbooks.Open("C:\Program Files\MyAddins\MyAddin.xla") 'for custom XLA addins