I'm trying to find a way to open Excel using Outlook VBA, but only if it's not already open. I managed to find some code on the internet that opens Excel, does changes and then closes it, but it doesn't behave nicely if the Excel workbook is already open(it does apply the changes, but it no longer closes the Excel workbook, and it simply leaves it with a grey interior; also, sometimes it doesn't even show in the explorer anymore and I have to close it from the task manager).
I would also greatly appreciate if someone could explain what most of the code does.
Public xlApp As Object
Public xlWB As Object
Public xlSheet As Object
Sub ExportToExcel()
Dim enviro As String
Dim strPath As String
'Get Excel set up
enviro = CStr(Environ("USERPROFILE"))
'the path of the workbook
strPath = enviro & "\Documents\test2.xlsx"
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
If Err <> 0 Then
Application.StatusBar = "Please wait while Excel source is opened ... "
Set xlApp = CreateObject("Excel.Application")
bXStarted = True
End If
On Error GoTo 0
'Open the workbook to input the data
Set xlWB = xlApp.Workbooks.Open(strPath)
Set xlSheet = xlWB.Sheets("Sheet1")
' Process the message record
On Error Resume Next
xlWB.Close 1
If bXStarted Then
xlApp.Quit
End If
End Sub
I know what the xlWb and xlSheet objects do, and how they're declared, and I also understand what the environ function and strPath string do, but I don't undestand why we need the bXStarted boolean, what Set xlApp = GetObject does, why the Application.StatusBar message doesn't get displayed, the difference between GetObject and CreateObjectand why so many error tests are needed.
Thanks in advance.
The difference between get object and create object is in the title, one will get open excel.application, if there is an error err<>0 then it creates an excel.application. I think you'll be getting a saveas message, as the file may not be saving, but open, and you're instructing it to save, the error resume next is skipping it . Try saving before just a .close If you remove the on error resume next the error wont be skipped and will be shown.
Sub explaination()
Dim blnDidICreateExcel As Boolean ' Please read MSDN on boolean
Dim objToHoldExcelCreatedOrNot As Object ' Please read MSDN on objects create/get
' Does the user have Excel open, if i try to get it, then there will be an error logically if not
Set objToHoldExcelCreatedOrNot = GetObject(, "Excel.Application")
' Was there an error
If Err <> 0 Then
' There was, so i need to create one
Set objToHoldExcelCreatedOrNot = CreateObject("Excel.Application")
blnDidICreateExcel = True ' Yes, i created it
End If
' Do the neccessary
' CLose the workbook
' Did i create this Excel, if so tidy up
If blnDidICreateExcel Then objToHoldExcelCreatedOrNot.Quit
End Sub
Related
When I have don't have the excel APP open, the following error is thrown :
ActiveX Component can't create object
Steps to reproduce issue :
1 Open Outlook, ALT + F11 And Insert the following sub :
Sub Test()
Dim myXL As New Excel.Application
Set myXL = GetObject(, "Excel.Application")
Set wb = myXL.Workbooks.Open("MyPath\MyXL.xlsx")
End Sub
Close ALL your excel files
Run the sub Test from outlook.
The Error will be thrown on :
Set myXL = GetObject(, "Excel.Application")
How can I avoid this error ?
A better option should be the next way, I think:
Dim objexcel As Object
On Error Resume Next 'firstly, try catching the existing open session, if any:
Set objexcel = GetObject(, "Excel.Application")
If err.Number <> 0 Then 'if no any existing session, create a new one:
err.Clear: Set objexcel = CreateObject("Excel.Application")
End If
On Error GoTo 0
Having a reference to 'Microsoft Excel ... Object library` you can declare
Dim objexcel As Excel.Application
and benefit of the intellisense suggestions...
It is also possible to find an Excel open session if you know the full name of a specific workbook open in it:
Set objExcel = GetObject(ThisWorkbook.fullName).Application
Debug.Print objExcel.hwnd
Or even for a new workbook, open by a third party application, in a new session, as "Book1":
Set objExcel = GetObject("Book1").Application
Debug.Print objExcel.hwnd
If the respective application drops new workbooks (and opens them in the same session), naming them as "Book2", "Book3" and so on, a loop building the workbook name bay concatenation of "Book" root with the incremented variable can be used to get it.
I'm currently trying to make a macro that opens a user defined excel spreadsheet, extracts some data for use in the word document and then closes it. My problem is that when I run the macro, the spreadsheet that I opened is still technically open as a background process in my task manager. I read on another stack overflow question that the reason is because visual basic will not release the reference object from excel until I close out of Microsoft Word. However, even after closing out of Word, the excel background process is still going and I can only stop it by ending the task in the task manager. To clarify, if I run the macro, close Word and then try to open the excel file, I can get in without telling me it's a read only file. However, if I don't close out of Word and I try to go into the spreadsheet after running the macro, then it tells me that it's a read only file. Below is the code I'm using that is causing this problem for me. Thanks to anyone who can help.
Sub UpdateProposal()
'Declares variables
Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim SpreadsheetPath As String
Dim xlSheet As Excel.Worksheet
Dim xlRange As Excel.Range
Dim ExcelWasNotRunning As Boolean
Dim ProposalInfoArr(1 To 30) As String
'Skips to ErrorHandler if user cancels out of file dialog
On Error GoTo ErrorHandler
'Display a Dialog Box that allows to select a single file.
'The path for the file picked will be stored in SpreadsheetPath variable
With Application.FileDialog(msoFileDialogFilePicker)
'Makes sure the user can select only one file
.AllowMultiSelect = False
'Filter to just the following types of files to narrow down selection options
.Filters.Add "Excel Files", "*.xlsx; *.xlsm; *.xls; *.xlsb", 1
'Show the dialog box
.Show
'Stores in SpreadsheetPath variable
SpreadsheetPath = .SelectedItems.Item(1)
End With
'If Excel is running, get a handle on it; otherwise start a new instance of Excel
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
If Err Then
ExcelWasNotRunning = True
Set xlApp = New Excel.Application
End If
'If you want Excel to be visible, you could add the line: xlApp.Visible = True here; but your code will run faster if you don't make it visible
'Open the workbook
Set xlBook = xlApp.Workbooks.Open(FileName:=SpreadsheetPath)
'''Extracts Data
'Quits out of Excel if it was not running previous to running the macro.
If ExcelWasNotRunning Then
xlApp.DisplayAlerts = False
xlApp.Quit
End If
'Make sure you release object references.
Set xlRange = Nothing
Set xlSheet = Nothing
Set xlBook = Nothing
Set xlApp = Nothing
'Ends the macro before the error handler
Exit Sub
'Ends Macro
ErrorHandler:
MsgBox "The following error occurred: " & Err.Description
End Sub
You are defining the objects correctly:
Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim xlRange As Excel.Range
but you forgot about the implicitly used Workbooks object... as most of the answers you will find do... which means it doesn't get released. So do it like this:
Dim SpreadsheetPath As String
Dim xlApp As Excel.Application
Dim xlBooks As Excel.Workbooks
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim xlRange As Excel.Range
SpreadsheetPath = "C:\MyPath\MyFile.xlsx"
Set xlApp = New Excel.Application
' Set xlApp = GetObject(, "Excel.Application") ' or attach to an existing one
Set xlBooks = xlApp.Workbooks
Set xlBook = xlBooks.Open(FileName:=SpreadsheetPath) ' you can use .Add instead if someone else may have it open already
Set xlSheet = xlBook.Worksheets(1)
Set xlRange = xlSheet.Range("A1")
' do stuff with the worksheet/range
xlRange.Value = "foo"
' the order matters
' just like it does
' when you create the objects
Set xlRange = Nothing
Set xlSheet = Nothing
xlBook.Close False
Set xlBook = Nothing
Set xlBooks = Nothing
xlApp.Quit
Set xlApp = Nothing
However, you may find that it still isn't getting released when you want, but it will get released when you close the program you are using to create it (in your case, MS-Word) as that is (presumably) when Windows does its built-in garbage collection.
Note: I removed the error handling just to keep it a clean example, but you can leave that in
i've got a subtle problem using VBA on MS Word. I try to refer to some workbooks that were opened before word was started up.
From within a short test-macro in word a simple
MsgBox Workbooks.Count
delievers a value of 0 although 3 (empty) workbooks are opened. When the 3 Workbooks are opened after Word was started, i get the correct value of 3.
How to fix this ?
jm2p Zeph
it's because you must get the running instance of Excel instead of creating a new one
the following code set an Excel application object trying to get any running instance first and then, should no excel session be already running, open a new one:
Option Explicit
Sub LateBindingExcel()
Dim xlApp As Object
Set xlApp = GetExcelObject
MsgBox xlApp.Workbooks.count
End Sub
Function GetExcelObject() As Object
Dim excelApp As Object
On Error Resume Next
Set excelApp = GetObject(, "Excel.Application") '<--| try getting a running Excel application
On Error GoTo 0
If excelApp Is Nothing Then Set excelApp = CreateObject("Excel.Application") '<--| if no running instance of Excel has been found then open a new one
Set GetExcelObject = excelApp '<--| return the set Excel application
End Function
Check this out:
'Option Explicit
'Option Explicit
Sub check()
Set objExcel = GetObject(, "Excel.Application")
Set wbs = objExcel.Workbooks
Debug.Print wbs.Count
Set objExcel = Nothing
Set wbs = Nothing
End Sub
I'm trying to update an Excel file from Outlook (Office 2010). How do I reference and access Excel?
As a simple test I'm trying to count the number of open workbooks. When I run this I get 0, even though there are 2 open.
Sub Test()
Dim xlApp As Excel.Application
Dim xlWBook As Excel.Workbook
Set xlApp = New Excel.Application
Debug.Print "xlApp.Workbooks.Count = " & xlApp.Workbooks.Count
On Error Resume Next
Set xlWBook = xlApp.Workbooks("Data.xlsx")
Err.Clear 'Clear error and open File Index
If xlWBook Is Nothing Then
Set xlWBook = xlApp.Workbooks.Open("C:\Users\Chris\Desktop\Data.xlsx")
End If
End Sub
This is what I use to detect Excel:
Dim xlApp As excel.Application
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
If Err.Number = 429 Then 'Excel not running
Set xlApp = CreateObject("Excel.Application")
End If
On Error GoTo 0
once xlApp is set, you can use xlApp.Workbooks.Count to count the worksheets
Note: This code will get the first one opened, if there are more than one instance of Excel to find
If you have to find a specific workbook, from this page, Set xlApp = GetObject("Book2").Application will find the workbook, even if it's not in the first instance. If the workbook is from a file, or already saved, replace book2 with the full path and filename - Side effect - this will also open the file if it is not already open
More usage info: http://msdn.microsoft.com/en-us/library/aa164798%28v=office.10%29.aspx
I have a VBScript code to open an excel file, run a macro and close it. Fine.
Now, the only thing I want to change is to leave the file open.
If I remove the 2 lines of code xlApp.activewindow.close and xlApp.Quit, then the workbook and the application are closed anyway, but they remain open in the background (Excel process still active in Task Manager). Hence, it is impossible to re-run the macro later on the same file by calling the script again (which is exactly what I want to do).
Why?
Here is the code:
Option Explicit
On Error Resume Next
MyTest
Sub MyTest()
Dim xlApp
Dim xlBook
Dim fpath
Dim fname
' Excel application running? if not, open Excel
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
If xlApp <> "Microsoft Excel" Then
Set xlApp = CreateObject("Excel.Application")
End If
Err.Clear
' correct Excel file open? if not, open it
fpath = "D:\Desktop\"
fname = "MyTest.xls"
xlApp.Workbooks(fname).Activate
If Err = 0 Then
' no error, so it has been possible to activate the workbook
Set xlBook = xlApp.Workbooks(fname)
Else
' unable to activate, so workbook was not open -> open it now
Set xlBook = xlApp.Workbooks.Open(fpath & fname, 0, True)
End If
Err.Clear
' now run the desired macro in the excel file
xlApp.Run "HelloWorld"
' WANT TO CHANGE THIS
xlBook.saved = True
xlApp.activewindow.close
' AND THIS
xlApp.Quit
Set xlBook = Nothing
Set xlApp = Nothing
End Sub
You just need to make your new instance of Excel visible. Do this right after creating it:
xlApp.Visible = True
This line of code will close your current activated workbook (by now, it is D:\Destop\MyTest.xls);
xlApp.activewindow.close
This line will quit Excel application;
xlApp.Quit