0

I want to close the active macro workbook inside the Userform_Terminate event. The problem I am facing is that, a ghost window of excel application lingers on even after workbook has been closed.

Have tried most of the suggested ways, I could get my hands on (described in detail in the code snippet) but to no avail. If anybody can help, much grateful.

NOTE: Have released almost all excel related objects from memory by setting it to nothing.

Code :

Private Sub UserForm_Terminate()

'   Application.DisplayAlerts = False    ' The excel ghost window lingers on
'   ThisWorkbook.Close , False
'   Application.DisplayAlerts = True
'
'   Application.DisplayAlerts = False    ' The excel ghost window lingers on
'   ThisWorkbook.Saved = True
'   ThisWorkbook.Close , False
'   Application.DisplayAlerts = True

'   Application.DisplayAlerts = False     'The excel ghost window lingers on.
'   ThisWorkbook.Close , False
'   Application.Quit
'   Application.DisplayAlerts = True

    Application.DisplayAlerts = False     'Ghost window is closed but also kills all instances of excel currently open
    Application.Quit
    Application.DisplayAlerts = True

   'NOTE:
   'Have released all excel related objects from memory by setting it to nothing, post use.

End Sub

Snap: enter image description here

Charlie
  • 175
  • 8
  • 1
    How do you start all Excel instances (in discussion)? – FaneDuru Jul 06 '21 at 08:21
  • Some things to try: Unload the form, call DoEvents then quit and if that does not work then call quit from the code that shows the form. – Charles Williams Jul 06 '21 at 08:24
  • @FaneDuru I meant to say, that on execution of Application.Quit statement, instead of just closing ThisWorkbook, it closes all excel files that are open in the system and which are not in anyway related to macro. – Charlie Jul 06 '21 at 08:43
  • @CharlesWilliams Hi, I will try that but I was hoping to put all controls in the form and not even let the user see the sheet. – Charlie Jul 06 '21 at 08:44
  • 3
    So, you mixed things... An excel instance is something different. I had in mind such a possibility when I asked to clarify the issue. You are talking about some workbooks open in **the same** excel instance/session. They share the same `Application.hwnd`. When you quit the application, this is the normal behavior: All workbooks open in the same session are closed. Now, let us clarify the `gost` issue... You try saying that the workbook keeping the form is closed, but an empty Excel window (without a workbook) remains. Is this supposition correct? What Excel version do you use? – FaneDuru Jul 06 '21 at 08:53
  • @FaneDuru okay, Thanks for clarifying. Hope now my problem statement is clear now. I will update the question. Yes, an empty window remains (pic attached) I am using Excel version 16.0 – Charlie Jul 06 '21 at 09:08
  • Please, look to the answer I posted and send some feedback – FaneDuru Jul 06 '21 at 09:24

1 Answers1

2

Well, your "gost" problem has the next explanation:

  1. An Excel session/instance means the same Application handler. If you open a workbook from the Excel existing interface, it is open in the same instance. Pressing Ctrl + F6 will jump to the next workbook open in the same instance...

If there are open workbooks not seen in the Ctrl + F6 sequence, this only means that they are open in a different instance.

Another instance is open, for instance :), in this way:

Din ExApp as Object
Set ExApp = CreateObject("Excel.Application")
  ExApp.Workbooks.add 'without this line, the instance is quit by itself...
  Set ExApp = Nothing 'this only releases the memory

You can see more open Excel instances (if they exist) looking in TaskManager and seeing more the one such application (Excel.exe)...

  1. When you close a workbook, and this specific workbook is the single one of the instance, the application Window, what you name a "gost" remains!. If there are some other workbooks open, the so named "gost" window disappears, too.

  2. In order to handle both situations, please try the next approach:

Private Sub UserForm_Terminate()
        If Workbooks.Count > OpenWb Then 
            ThisWorkbook.Close , False
        Else
            Application.Quit
        End If
End Sub

Function OpenWb() As Long
   Dim count As Long, wb As Workbook, arr
   For Each wb In Workbooks
        arr = Split(wb.Name, ".")
        If UCase(arr(UBound(arr))) = "XLSB" Then count = count + 1
   Next
   OpenWb = count + 1
End Function

Quitting the application is done here only because you asked for it... When you try programmatically to open and close many workbooks, it is more efficient to keep the application open. To open a new instance takes time. To open a workbook in an existing instance takes less time... But to do that, your code must find that existing instance:

Sub testExcelInstance()
  Dim Ex As Object
  
  On Error Resume Next
  Set Ex = GetObject(, "Excel.Application")
  If Ex Is Nothing Then
        Err.Clear: On Error GoTo 0
        Set Ex = CreateObject("Excel.Application")
  End If
  On Error GoTo 0
  Ex.Workbooks.Add 'just doing something after having the Excel instance object
End Sub

Releasing the objects from the memory does not do anything, in terms of the object itself existence. If physically disappears only if you quit it.

FaneDuru
  • 38,298
  • 4
  • 19
  • 27
  • I won't hardcode this `Workbooks.Count > 1` as this might easily change or be different by any other users. Better to use a [function to check if `PERSONAL.XLSB` is open](https://stackoverflow.com/a/9374481) or not. – Pᴇʜ Jul 06 '21 at 09:47
  • @Pᴇʜ Of course. But I only tried to demonstrate how that "gost" window can be handled... Theoretically, more `.xlsb` workbooks may exist. They do not show a window (even it exists), but they are counted as workbooks. It is not complicated to create a function to count all workbooks having this extension. – FaneDuru Jul 06 '21 at 09:53
  • 1
    I'm not critizising (you got my vote) just wanted to mention this thought for future readers. – Pᴇʜ Jul 06 '21 at 09:56
  • @Pᴇʜ I didn't take your comment like a criticism. I only tried explaining why I did not focus too much on this aspect. But you are right. I will create a function determining the correct number to be taken in consideration. Thanks! – FaneDuru Jul 06 '21 at 09:59
  • @FaneDuru Hi, thanks for the explanation. It certainly helped me understand a few things but the problem still remains. The moment application.exit is executed, every excel file open is getting closed. The workbook.close has that ghost window hanging around, that's why i am forced to use quit method. – Charlie Jul 06 '21 at 10:00
  • @Charlie They all close because they are all in the same instance. Even if you see multiple windows they can still live in the same instance. And `.Quit` ends the entire instance. What is the result of `Workbooks.Count` right before closing that workbook. – Pᴇʜ Jul 06 '21 at 10:04
  • @Pᴇʜ So, is there any solution to that ghost window hanging around which appears after executing 'Thisworkbook.close, false' line – Charlie Jul 06 '21 at 10:07
  • @Charlie Did you try the code I proposed, to solve this pseudo 'gost' problem? Now I edited the answer and placed a function able to calculate the xlsb workbooks (if they exist). So, **if there are other workbooks open**, do you try saying that the empty window ("gost") still remains? I don't think so... – FaneDuru Jul 06 '21 at 10:08
  • What is the output of `Debug.Print Windows.Count, Workbooks.Count` in the immediate window right before you run `Thisworkbook.close, false`? – Pᴇʜ Jul 06 '21 at 10:09
  • @Pᴇʜ Now, if he will use the updated code (including the function to calculate the real counted workbooks) it should work as he needs... Only if the answer of my previous question (the "gost" behavior in case of other open workbooks) is a strange one, for his installation, but I don't think so... – FaneDuru Jul 06 '21 at 10:10
  • 1
    @FaneDuru I find it strange because if there are other workbooks in the same instance then the ghost window should not appear when closing a workbook. It should only appear if the closed workbook was the last one. So clearly something odd is going on here. – Pᴇʜ Jul 06 '21 at 10:13
  • @Pᴇʜ I am waiting for his answer at that specific question... – FaneDuru Jul 06 '21 at 10:14
  • @FaneDuru Okay, now I actually understood your code. Thanks it is working as intended but say if I wanna remove the quit method altogether, the problem still remains though i.e if only macro is open and I use thisworkbook.close, false our ghost window makes re appearance. Any solutions for this ? – Charlie Jul 06 '21 at 10:14
  • @Charlie What problem still remains? Do you mean that, **if there are other open workbooks** and you try closing the workbook, **does the "gost" remain**? This should not be possible... If not this is a problem, please try describing it. – FaneDuru Jul 06 '21 at 10:16
  • @FaneDuru as in if there is only macro open and I want to close that without using quit then ghost window will remain right ? – Charlie Jul 06 '21 at 10:19
  • @Pᴇʜ Sorry for late reply. I sorta understood the code now. The workbooks.count was 3 as there were three excel files open – Charlie Jul 06 '21 at 10:20
  • 1
    @Charlie Yes, but this is the normal Excel behavior and it is a benefit. I tried explaining **why**... You can programmatically open another workbook, without loosing time with Excel application loading. It is enough to open **the existing instance**. I tried showing how to proceed in such a case. – FaneDuru Jul 06 '21 at 10:20
  • @FaneDuru I see. Thank you very much for explaining it to me. If u don't mind could u direct me to some sources where I can understand the concepts of window handles. – Charlie Jul 06 '21 at 10:23
  • @Charlie I think that now it is only good to understand that Windows (OS) allocates a **unique** handle to each window. But Application handle is a little different. In the same instance (the same `Application.hwnd`) there may be more windows... – FaneDuru Jul 06 '21 at 10:27