determine if Excel is open

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi,

i have te following code behind a button:

' Create an instance of Excel and add a workbook
Set xlApp = CreateObject("Excel.Application")
Set xlWb = xlApp.Workbooks.Add
Set xlWs = xlWb.Worksheets("Sheet1")

The only problem is, if users click the button 20 times, there are 20
instances of Excel open on the machine, thereby slowing computer performance.
I want Excel to be oneped ONLY if it is not currently opened on the users
machine to prevent multiple excel instances. how can I achieve this?

Thanks in advance,
-geebee
 
' Create an instance of Excel and add a workbook
Set xlApp = CreateObject("Excel.Application")
Set xlWb = xlApp.Workbooks.Add
Set xlWs = xlWb.Worksheets("Sheet1")

There is a similar function called GetObject() Check it out in the help
file.

Make a VBA function like the one below, and then use this code:

Set xlApp = GetExcel()
Set xlWb = xlApp.Workbooks.Add
Set xlWs = xlWb.Worksheets("Sheet1")



Public Function GetExcel() As Excel.Application

' Returns a live instance of Microsoft Excel, whether
' one is already running or not. If more than one version
' of Excel is installed, it will return whichever one was
' installed most recently. BE CAREFUL: If the user has
' already started Excel for some other purpose, this
' function may return the user's other instance of Excel
' which may or may not be appropriate.

On Error Goto GetExcelError

Dim xl As Excel.Application

Set xl = GetObject( , "Excel.Application")

If xl Is Nothing Then Set xl = CreateObject("Excel.Application")

GetExcelExit:
Set GetExcel = xl
Set xl = Nothing
Exit Function

GetExcelError:
If xl Is Nothing Then
' Maybe Excel is not installed.
Else
' Something else happened
End If

End Function
 
geebee said:
Hi,

i have te following code behind a button:

' Create an instance of Excel and add a workbook
Set xlApp = CreateObject("Excel.Application")
Set xlWb = xlApp.Workbooks.Add
Set xlWs = xlWb.Worksheets("Sheet1")

The only problem is, if users click the button 20 times, there are 20
instances of Excel open on the machine, thereby slowing computer performance.
I want Excel to be oneped ONLY if it is not currently opened on the users
machine to prevent multiple excel instances. how can I achieve this?

Thanks in advance,
-geebee

I vaguely recall that some API calls can return the list of processes
currently running on a machine. I have the code somewhere in some mdb
file residing somewhere on some machine at home so try Googling first.

James A. Fortune
(e-mail address removed)
 
James said:
I vaguely recall that some API calls can return the list of processes
currently running on a machine. I have the code somewhere in some mdb
file residing somewhere on some machine at home so try Googling first.

James A. Fortune
(e-mail address removed)

This code was adapted about five years ago to run on W98 from somewhere
like microsoft.public.vb.winapi or like:

http://groups.google.com/group/microsoft.public.developer.outlook.addins/msg/de59703b57af548b?hl=en&

Look at Case 2 in the link above for Windows NT/2000/XP.

'Begin Module Code

Option Compare Database
Option Explicit


Public Const PROCESS_QUERY_INFORMATION = 1024
Public Const PROCESS_VM_READ = 16
Public Const MAX_PATH = 260
Public Const STANDARD_RIGHTS_REQUIRED = &HF0000
Public Const SYNCHRONIZE = &H100000
'STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF
Public Const PROCESS_ALL_ACCESS = &H1F0FFF
Public Const hNull = 0
Private Const MAX_MODULE_NAME32 As Integer = 255
Private Const MAX_MODULE_NAME32plus As Integer = MAX_MODULE_NAME32 + 1
Public Const TH32CS_SNAPPROCESS = &H2&
Public Const TH32CS_SNAPMODULE = &H8&

Public Declare Sub ExitProcess Lib "kernel32.dll" (ByVal uExitCode As Long)

Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess
As Long, ByVal uExitCode As Long) As Long

Public Declare Function GetExitCodeProcess Lib "kernel32.dll" (ByVal
hProcess As Long, lpExitCode As Long) As Long

Public Declare Function Process32First Lib "kernel32.dll" ( _
ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long

Public Declare Function Process32Next Lib "kernel32" ( _
ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long

Public Declare Function CloseHandle Lib "kernel32.dll" _
(ByVal Handle As Long) As Long

Public Declare Function CreateToolhelp32Snapshot Lib "kernel32" ( _
ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long

Public Declare Function Module32First Lib "kernel32" ( _
ByVal hSnapshot As Long, lpme As MODULEENTRY32) As Long

Public Declare Function Module32Next Lib "kernel32" ( _
ByVal hSnapshot As Long, lpme As MODULEENTRY32) As Long

Public Declare Function OpenProcess Lib "kernel32.dll" _
(ByVal dwDesiredAccessas As Long, ByVal bInheritHandle As Long, _
ByVal dwProcId As Long) As Long

Public Declare Function EnumProcesses Lib "psapi.dll" _
(ByRef lpidProcess As Long, ByVal cb As Long, _
ByRef cbNeeded As Long) As Long

Public Declare Function GetModuleFileNameExA Lib "psapi.dll" _
(ByVal hProcess As Long, ByVal hModule As Long, _
ByVal ModuleName As String, ByVal nSize As Long) As Long

Public Declare Function EnumProcessModules Lib "psapi.dll" _
(ByVal hProcess As Long, ByRef lphModule As Long, _
ByVal cb As Long, ByRef cbNeeded As Long) As Long

Public Declare Function GetVersionExA Lib "kernel32" _
(lpVersionInformation As OSVERSIONINFO) As Integer

Public Type PROCESSENTRY32
dwSize As Long 'Specifies the length, in bytes, of the
structure.
cntUsage As Long 'Number of references to the process.
th32ProcessID As Long 'Identifier of the process.
th32DefaultHeapID As Long 'Identifier of the default heap for the
process.
th32ModuleID As Long 'Module identifier of the process.
(Associated exe)
cntThreads As Long 'Number of execution threads started by
the process.
th32ParentProcessID As Long 'Identifier of the process that created
the process being examined.
pcPriClassBase As Long 'Base priority of any threads created
by this process.
dwFlags As Long 'Reserved; do not use.
szExeFile As String * MAX_PATH 'Path and filename of the
executable file for the process.
End Type
Public Type MODULEENTRY32
dwSize As Long 'Specifies the length, in bytes, of the
structure.
th32ModuleID As Long 'Module identifier in the context of the
owning process.
th32ProcessID As Long 'Identifier of the process being examined.
GlblcntUsage As Long 'Global usage count on the module.
ProccntUsage As Long 'Module usage count in the context of the
owning process.
modBaseAddr As Long 'Base address of the module in the context
of the owning process.
modBaseSize As Long 'Size, in bytes, of the module.
hModule As Long 'Handle to the module in the context of the
owning process.
szModule As String * MAX_MODULE_NAME32plus 'String
containing the module name.
szExePath As String * MAX_PATH 'String containing the
location (path) of the module.
End Type

Public Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long '1 = Windows 95.
'2 = Windows NT
szCSDVersion As String * 128
End Type

Public Function getVersion() As Long
Dim osinfo As OSVERSIONINFO
Dim retvalue As Integer
osinfo.dwOSVersionInfoSize = 148
osinfo.szCSDVersion = Space$(128)
retvalue = GetVersionExA(osinfo)
getVersion = osinfo.dwPlatformId
End Function
Public Function StrZToStr(s As String) As String
StrZToStr = Left$(s, Len(s) - 1)
End Function

Public Function IsOutlookRunning(ByRef lngProcessID As Long) As Boolean

' Case 1 'Windows 95/98

Dim f As Long
Dim sname As String
Dim hSnap As Long
Dim proc As PROCESSENTRY32

IsOutlookRunning = False
lngProcessID = 0
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
If hSnap = hNull Then Exit Function
proc.dwSize = Len(proc)
' Iterate through the processes
f = Process32First(hSnap, proc)
Do While f
sname = StrZToStr(proc.szExeFile)
If InStr(1, sname, "OUTLOOK.EXE", vbTextCompare) > 1 Then
IsOutlookRunning = True
lngProcessID = proc.th32ProcessID
End If
f = Process32Next(hSnap, proc)
Loop

End Function
Public Function IsIERunning() As Boolean

' Case 1 'Windows 95/98

Dim f As Long
Dim sname As String
Dim hSnap As Long
Dim proc As PROCESSENTRY32

IsIERunning = False
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
If hSnap = hNull Then Exit Function
proc.dwSize = Len(proc)
' Iterate through the processes
f = Process32First(hSnap, proc)
Do While f
sname = StrZToStr(proc.szExeFile)
'MsgBox (sname)
If InStr(1, sname, "IEXPLORE.EXE", vbTextCompare) > 1 Then
IsIERunning = True
f = Process32Next(hSnap, proc)
Loop

End Function

Public Function IsWordRunning() As Boolean

' Case 1 'Windows 95/98

Dim f As Long
Dim sname As String
Dim hSnap As Long
Dim proc As PROCESSENTRY32

IsWordRunning = False
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
If hSnap = hNull Then Exit Function
proc.dwSize = Len(proc)
' Iterate through the processes
f = Process32First(hSnap, proc)
Do While f
sname = StrZToStr(proc.szExeFile)
'MsgBox (sname)
If InStr(1, sname, "WINWORD.EXE", vbTextCompare) > 1 Then
IsWordRunning = True
f = Process32Next(hSnap, proc)
Loop

End Function
Public Sub CloseAccess()
' Case 1 'Windows 95/98

Dim f As Long
Dim sname As String
Dim hSnap As Long
Dim proc As PROCESSENTRY32
Dim lngTemp As Long
Dim lngProcessID As Long

lngProcessID = 0
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
If hSnap = hNull Then Exit Sub
proc.dwSize = Len(proc)
' Iterate through the processes
f = Process32First(hSnap, proc)
Do While f
sname = StrZToStr(proc.szExeFile)
'MsgBox (sname)
If InStr(1, sname, "MSACCESS.EXE", vbTextCompare) > 1 Then
lngProcessID = proc.th32ProcessID
'Close all instances of Access
'MsgBox (lngProcessID)
Call ExitProcess(GetExitCodeProcess(lngProcessID, 0))
CloseHandle (lngProcessID)
End If
f = Process32Next(hSnap, proc)
Loop

End Sub
'End Module Code

Everything but Excel :-).

James A. Fortune
(e-mail address removed)
 
That's very elegant, James, but verbose in the extreme. How about this ...

Public Function IsExcelOpen() As Boolean
Dim objExcel As Object
On Error Resume Next
Set objExcel = GetObject("Excel.Application")
If Err.Number = 0 Then IsExcelOpen = True Else IsExcelOpen = False
Set objExcel = Nothing
End Function
 
Ooops, I was typing form memory, and missed the GetObject line.
It should read with an empty first argument and a comma, like this ...

Set objExcel = GetObject( , "Excel.Application")

Also the result can be simplified to ...
IsExcelOpen = (Err.Number = 0)
 
Danny said:
That's very elegant, James, but verbose in the extreme. How about this ...

Public Function IsExcelOpen() As Boolean
Dim objExcel As Object
On Error Resume Next
Set objExcel = GetObject("Excel.Application")
If Err.Number = 0 Then IsExcelOpen = True Else IsExcelOpen = False
Set objExcel = Nothing
End Function

Danny, thanks for posting your code. Although the code I posted was
from a long time ago, I actually prefer verbose in the extreme to
relying on On Error. Got anything in between that doesn't have that
problem?

James A. Fortune
(e-mail address removed)
 
No, I'm afraid I don't.

I know there was a recent discussion of whether or not you would _ever_
want to allow an error and perhaps On Error Resume Next is inherently
evil, but it sure tightens up the code for this process :-)
 
Danny said:
No, I'm afraid I don't.

I know there was a recent discussion of whether or not you would _ever_
want to allow an error and perhaps On Error Resume Next is inherently
evil, but it sure tightens up the code for this process :-)

Thanks again Danny. Sometimes On Error is unavoidable but I try to
limit my usage of On Error to those cases except where an app needs to
be distributed commercially. In that case the safety net is a sine qua
non. The code for, say, just Outlook wasn't too verbose but you're
right that the code you posted is much shorter for those who do not mind
using On Error.

James A. Fortune
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top