Excel 2010 does not see all open workbooks

rdwray

New member
Joined
Mar 25, 2017
Messages
38
Reaction score
0
Points
0
Excel Version(s)
2010
If a workbook is already open and a second one is opened in a separate instance, the second workbook does not see the first one; it will see any that are opened afterwards.

The problem is that the Excel process does not end if VBA macros are being used so Taskkill has to be used to end the process which will close all open workbooks - Workbooks.Count cannot be used because any previously opened workbooks are not seen. If Taskkill is used to close the workbook, the Excel instance still runs. Does anyone have an answer to this one???
 
Last edited:
This is confusing to me. Separate instances are now allowed but no commands were added to easily get the other instances.

Of course one can use a VBS file to kill all instances. Maybe you would want to use similar code in the close event for one instance?

Another solution might be to close that other file and/or instance? If you know the filename, getting the other instance is fairly easy. An API method is generally used for that.
 
This is confusing to me. Separate instances are now allowed but no commands were added to easily get the other instances.

Of course one can use a VBS file to kill all instances. Maybe you would want to use similar code in the close event for one instance?

Another solution might be to close that other file and/or instance? If you know the filename, getting the other instance is fairly easy. An API method is generally used for that.
It is possible to open more than one instance, that is what has taken place when there are more than one Excel windows.

Want to close the ActiveWorkbook only, not any others.

Any Workbook can be open at any time. Need to have the Workbook names to make it work.
 
I still don't understand. Obviously, many instances can be open.

ActiveWorkbook.Close is the way to close the current instance's workbook.

If you don't know the workbook names to close in other instances, you can iterate the instances and workbooks as Leith Ross demonstrated. This is the API method that I discussed.
Code:
'Leith Ross, http://www.vbaexpress.com/forum/showthread.php?60682-application-windows-object

' Written:  September 11, 2017
' Author:   Leith Ross
' Summary:  Searches all open instances of Excel on the user's desktop
'           for a workbook matching the given nam. When a match is found
'           an object reference to the workbook is returned. If no match
'           is found then the value returned is Nothing.
 
Private Const OBJID_NATIVEOM As Long = &HFFFFFFF0
 
 
Type GUID
    lData1 As Long
    iData2 As Integer
    iData3 As Integer
    aBData4(0 To 7) As Byte
End Type
 
 
Private Declare PtrSafe Function IIDFromString _
  Lib "ole32.dll" _
  (ByVal lpszIID As String, _
  ByRef lpiid As GUID) _
  As Long
 
 
Private Declare PtrSafe Function FindWindowEx _
  Lib "user32.dll" Alias "FindWindowExA" _
  (ByVal hWnd1 As LongPtr, _
  ByVal hWnd2 As LongPtr, _
  ByVal lpsz1 As String, _
  ByVal lpsz2 As String) _
  As LongPtr
 
Private Declare PtrSafe Function AccessibleObjectFromWindow _
  Lib "oleacc.dll" _
  (ByVal hwnd As LongPtr, _
  ByVal dwId As Long, _
  ByRef riid As GUID, _
  ByRef ppvObject As Object) _
  As Long
 
Function GetWorkbookByName(ByVal wkbName As String) As Object
    Dim CLSID   As String
    Dim IDisp   As GUID
    Dim n       As Long
    Dim ret     As Long
    Dim xlDesk  As LongPtr
    Dim xlHwnd  As LongPtr
    Dim xlWkb   As LongPtr
    Dim Wnd     As Object
    Dim Wkb     As Workbook
    Dim XLapp   As Excel.Application
     
    If wkbName = "" Then
        MsgBox "Workbook Name Is Missing", vbExclamation
        Exit Function
    End If
     
    CLSID = StrConv("{00020400-0000-0000-C000-000000000046}", vbUnicode)
    ret = IIDFromString(CLSID, IDisp)
     
    Do
        xlHwnd = FindWindowEx(0, xlHwnd, "XLMAIN", vbNullString)
        If xlHwnd = 0 Then Exit Do
         
        xlDesk = FindWindowEx(xlHwnd, 0&, "XLDESK", vbNullString)
        xlWkb = FindWindowEx(xlDesk, 0&, "EXCEL7", vbNullString)
         
        If xlWkb <> 0 Then
            ret = AccessibleObjectFromWindow(xlWkb, OBJID_NATIVEOM, IDisp, Wnd)
            If ret = 0 Then
                Set XLapp = Wnd.Parent.Parent
                For n = 1 To XLapp.Workbooks.Count
                    Set Wkb = XLapp.Workbooks(n)
                    If Wkb.Name = wkbName Then
                        Set GetWorkbookByName = Wkb
                        Exit Function
                    End If
                Next n
            End If
        End If
    Loop
     
End Function




Sub Collects()
  Dim Wkb As Workbook
  Set Wkb = GetWorkbookByName("Excel1.xlsx")
  If Not Wkb Is Nothing Then
    ThisWorkbook.Worksheets("Sheet1").Range("A1").Value = Wkb.Worksheets("Sheet1").Range("A1").Value
  End If
End Sub
 
I still don't understand. Obviously, many instances can be open.

ActiveWorkbook.Close is the way to close the current instance's workbook.

If you don't know the workbook names to close in other instances, you can iterate the instances and workbooks as Leith Ross demonstrated. This is the API method that I discussed.
Code:
'Leith Ross, http://www.vbaexpress.com/forum/showthread.php?60682-application-windows-object

' Written:  September 11, 2017
' Author:   Leith Ross
' Summary:  Searches all open instances of Excel on the user's desktop
'           for a workbook matching the given nam. When a match is found
'           an object reference to the workbook is returned. If no match
'           is found then the value returned is Nothing.
 
Omitted on purpose.
What is not being understood is that if an instance is opened and then a second instance is opened, the second instance will not return the name of the first instance.
 
Any instance can get access to the other instance(s). It is just not evident to you I guess nor obvious to most. This is why I showed an API code example to do that. It just needs a few modifications to do whatever you need. I still don't know what you need, call one other instance, all other instances, one specific workbook if open, etc.
 
Any instance can get access to the other instance(s). It is just not evident to you I guess nor obvious to most. This is why I showed an API code example to do that. It just needs a few modifications to do whatever you need. I still don't know what you need, call one other instance, all other instances, one specific workbook if open, etc.

Leif's code works with modification, but there are other issues that are still causing problems so I am going to hang this one up and move on. Thanks for the help Kenneth.
 
Make that Leith's code...
 
Sorry I couldn't help. Defining the problem can be the biggest part for problem solving.

For the edification of others that might see this thread, below are the two other methods that I mentioned.

1. Call in a Workbook's close event. Put this in a Module and call from the event.
Code:
rem https://social.msdn.microsoft.com/Forums/office/en-US/93958cdb-1a4d-490b-9e47-5be25e430a21/excel-not-quitting-from-vbscript?forum=exceldev

Function KillProcess()
   On Error Resume Next 
   Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}" & "!\\.\root\cimv2")
 
   Set colProcess = objWMIService.ExecQuery ("Select * From Win32_Process")
   For Each objProcess in colProcess
      rem If LCase(objProcess.Name) = LCase("firefox.exe") OR LCase(objProcess.Name) = LCase("iexplore.exe") Then
      If LCase(objProcess.Name) = LCase("excel.exe") Then
         objWshShell.Run "TASKKILL /F /T /IM " & objProcess.Name, 0, False
         objProcess.Terminate()
         'MsgBox "- ACTION: " & objProcess.Name & " terminated"
      End If
   Next
End Function

2. In a VBS file:
Code:
Dim objWMIService, objProcess, colProcess

Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2") 
Set colProcess = objWMIService.ExecQuery ("Select * from Win32_Process Where Name = " & "'EXCEL.EXE'")


For Each objProcess in colProcess
    objProcess.Terminate()
Next
 
There is no way that I can find to fix Excel's problem when closing a workbook except open each one in a separate window with a shortcut.

Shortcut: "Path to Excel" "Path to Workbook to open"
i.e. "C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.EXE" "C:\Backup\Notes.xlsm"
 
If a workbook is already open and a second one is opened in a separate instance, the second workbook does not see the first one;

Why do you use several instances of Excel ?
 
Why do you use several instances of Excel ?

Because in some cases the Excel process does not shut down when using a UserForm so it has to be forced closed or the next time you try to open the same workbook you get "... locked for editing". When forcing Excel to close it will shut down all open workbooks unless some means is used to bypass the others. When using separate instances, "Excel.Application.Quit" in "Private Sub Workbook_BeforeClose(Cancel As Boolean)" can be used in every workbook to force Excel to close and will not shut down other open workbooks.
 
Because in some cases the Excel process does not shut down when using a UserForm
I don't believe this. Can you illustrate ?

If you use getobject("G:\OF\example.xlsx"), no new Excel instances will be created.
 
I don't see any userform, nor any coding.
You probably create this problem yourself by using wrong coding.
Without showing it you can't be helped.
 
I don't see any userform, nor any coding.
You probably create this problem yourself by using wrong coding.
Without showing it you can't be helped.

The code consists of 4 forms and 11 modules. I am tired of your arrogance, put it on someone else.
 
You get tired very fast, check a physician unless you don't want to be helped.
 
-
 
Last edited:
You get tired very fast, check a physician unless you don't want to be helped.

snb, enough already. This was totally out of line. If you don't want to help this user, then don't help. But don't come in and mock and belittle them. That doesn't help anyone and isn't the environment I want on this forum.

rdwray, I'm sorry you had to put up with this.
 
snb, enough already. This was totally out of line. If you don't want to help this user, then don't help. But don't come in and mock and belittle them. That doesn't help anyone and isn't the environment I want on this forum.

rdwray, I'm sorry you had to put up with this.

No need for you to apologize Ken, you can't control a comment before it is made. Just wanted to let you know what was going on so that you can keep a good forum.
 
Back
Top