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:
Well, your "gost" problem has the next explanation:
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)...
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.
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.
Related
I'm having an VB6 application that opens an excel macro enabled file using workbooks.open method. Inside this file, there is an userform that gonna be automatically opened when the file is opened. The problem is the workbooks.open method in vb6 application keeps running and does not jump to next line even when I close my userform (I do have codes to close workbook, quit excel app when the userform is closed). I can only close the interface of my userform but Excel still running in background. As long as I dont close the Excel app in task manager, my vb6 does not terminate excel process and of course it will not jump to next line either.
Here is my code in vb6 to open excel file that contains the userform above
As I said, workbooks.open method works but it does not terminate and keeps the excel app runnning in background
P/s: don't mind the Japanese characters
Private Sub Form_Load()
Dim xlapp
Dim xlwkb
If Not App.PrevInstance Then
Set xlapp = CreateObject("excel.application")
Me.Hide
On Error Resume Next
Set xlwkb = xlapp.workbooks.open("C:\Users\david\Desktop\sale-system\fixedfile.xlsm", Readonly:= True)
Set xlwkb = Nothing
If Not xlapp Is Nothing Then
xlapp.Visible = True
xlapp.Application.quit
Set xlapp = Nothing
End If
Unload Me
Else
MsgBox "プログラムが既に起動されています!", vbInformation, "売上管理システム"
Unload Me
End If
End Sub
Here is my code in excel file when close the userform
Application.DisplayAlerts = False
ThisWorkbook.Close False
Application.Visible = True
Application.Quit
End
I really need to solve this problem in this week, any solution?
Thank you guys in advance and please pardon for my english
Here is some images. I hope they will help you guys to understand my problem
This happens when I use Thisworkbook.close False statement:
This happens when I dont use Thisworkbook.close False statement:
Inside this file, there is an userform that gonna be automatically opened when the file is opened.
when I close my userform (I do have codes to close workbook, quit excel app when the userform is closed).
You are doing this incorrectly. Do not close/quit it from the UserForm. Do it from VB6 form. This way, vb6 will be able to handle and clear the objects.
Here, try this (I already tried it and it works...). This will not leave an instance of Excel running. I have commented the code. But if you still have questions then simply ask.
Note: Before you try this (Just for testing purpose), close all Excel application. Even from the task manager.
Private Sub Form_Load()
Dim oXLApp As Object
Dim oXLWb As Object
Dim ICreateatedExcel As Boolean
'~~> Establish an EXCEL application object
On Error Resume Next
Set oXLApp = GetObject(, "Excel.Application")
'~~> If not found then create new instance
If Err.Number <> 0 Then
Set oXLApp = CreateObject("Excel.Application")
'~~> I created instance of Excel
ICreateatedExcel = True
End If
Err.Clear
On Error GoTo 0
'~~> Check if you have an instance of Excel
If oXLApp Is Nothing Then
MsgBox "Unable to get an instance of Excel.", vbCritical, "Excel is Installed?"
Exit Sub
End If
Me.Hide
'~~> Show Excel
oXLApp.Visible = True
'~~> Open file
Set oXLWb = oXLApp.Workbooks.Open("C:\Tester.xlsm")
'~~> This and other lines below will not run till the
'~~> time you close the userform in Excel
'~~> Close the workbook
oXLWb.Close (False) '<~~ Set this to True if you want to save changes
Set oXLWb = Nothing
'~~> If I created Excel then quit
If ICreateatedExcel = True Then oXLApp.Quit
Set oXLApp = Nothing
Unload Me
End Sub
I have two separated workbooks with macroces: Book1 with Macro1 and Book2 with Macro2.
Macro1 is simple code to:
hidely open Book2 (has an open password: 1111);
write "test" in A1 Active Sheet of Book2;
run Macro2 from Book2, which is simple MsgBox "Hello! I am an msgbox
from Book2";
close Book2 with saving.
Sub Macro1()
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.DisplayAlerts = False
Dim myWb As Workbook
Set myWb = Workbooks.Open(ThisWorkbook.Path & "/" & "Book2.xlsb", True, False, , "1111")
myWb.Unprotect ("1111")
Cells(1, 1) = "test"
myWb.IsAddin = True
Application.Run "'Book2.xlsb'!Macro2"
myWb.Close savechanges:=True
Application.DisplayAlerts = True
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Sub Macro2()
MsgBox "Hello! I am an msgbox from Book2"
End Sub
I emphasize that everything should be done secretly and the user should not see neither Book2 nor any flashes, etc.
But when code comes to the saving step a window pops up on the screen, which, by the way, can be ignored and the code will continue to run/execute but anyway it's a PROBLEM I want get rid of:
password pop-up window
What I noticed:
If I remove the opening password from book2, the saving will be successfull and without pop-up dialogs. But I need Book2 opening protected.
I tried to modify code, but results are not unsatisfactory due to
screen blinking, screenshots below:
OK
V1-NOK
V2-NOK
V1: myWb.IsAddin = True is deleted/commented
Application.Run "'Book2.xlsb'!Macro2"
myWb.Close savechanges:=True
V2: ON/OFF IsAddin = True before/after Macro2 executing
myWb.IsAddin = True
Application.Run "'Book2.xlsb'!Macro2"
myWb.IsAddin = False
myWb.Close savechanges:=True
Please, try the next way. It will open the workbook in a new session, will write in its first sheet and run the macro. But a macro sending a message from a non visible session/window is not the best idea. In order to see the message, please move the cursor over the Excel workbooks icons on taskbar, select the MsgBox window and press OK. A better idea would be do avoid sending messages. The code should run as you need:
Sub HiddenWBOpenRunMacro()
Dim newEx As Excel.Application, myWb As Workbook
Set newEx = CreateObject("Excel.Application")
'Open the workbook in the newly created session:
Set myWb = newEx.Workbooks.Open(ThisWorkbook.Path & "/" & "Book2.xlsb", , , , "1111")
myWb.Sheets(1).cells(1, 1).Value = "Test" 'write in its first sheet
myWb.Application.Run "'Book2.xlsb'!Macro2" 'run the macro
myWb.Close True 'close the workbook, saving it
newEx.Quit 'quit the session
End Sub
If ThisWorkbook not in Excel Trusted Locations it must be added.
I have an unexpected display when closing a new workbook !
I launch my macro from the command line.
Application is made invisible from workbook_open :
Sub workbook_open()
Application.Visible = False
UserForm1.Show
Application.Visible = True
End Sub
UserForm1 contains a single button.
-> Only the userform is displayed.
Pressing the button starts the following code :
Sub UnexpectedDisplay()
Dim NewBook As Workbook
Debug.Print "_______________"
Application.Visible = False
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set NewBook = Workbooks.Add
With NewBook
.Title = "MyTitle"
.Subject = "Display"
.SaveAs Filename:="MyWorkbook"
End With
Debug.Print ActiveWorkbook.Name
MsgBox "New workbook added"
NewBook.Close SaveChanges:=True
Debug.Print ActiveWorkbook.Name
MsgBox "Workbook closed"
Application.DisplayAlerts = True
End Sub
The first msgbox is displayed : "New workbook added"
-> Only the msgbox is displayed.
Press "Ok"
The second msgbox is displayed : "Workbook closed"
Debug Trace :
_______________
MyWorkbook.xlsx
MyMacroFile.xlsm
-> A workbook becomes visible
( when MyMacroFile.xlsm is opened?).
-> Question : How to avoid this.
Please try this code.
Sub TestInVis()
Dim Wb As Workbook
Dim Fn As String
Fn = FileOpenName("Test")
Application.ScreenUpdating = False
Set Wb = Workbooks.Open(Fn)
Wb.Windows(1).Visible = False
Application.ScreenUpdating = True
End Sub
Before doing so, please set the variable Fn to contain a valid filename, complete with its path. (I used a function called FileOpenName which calls a FilePicker dialog.) The code will open the specified workbook and hide its window, leaving the previously displayed window on top.
In my test, the Open action didn't re-instate Screen Updating but I'm not sure that disabling it makes a difference. There is a short flicker while the workbook is being opened and I thought it was less pronounced while ScreenUpdating = False. It will be prolonged, however, if the file is large. One way or the other, the file opens invisibly and you can access it by the object variable to which it was assigned.
Next, I tested the same procedure with Workbooks.Add. All I said about about Open applies equally, except that the new workbook is very small, of course. Therefore it's even harder to tell whether ScreenUpdating really makes a difference.
I have two workbooks on a shared network drive:
Workbook A (Table)
Workbook B (Pivot Table -Connected to source Workbook A)
I'm trying to, when Workbook B is opened, run macro and do this:
Unprotect a certain worksheet on Workbook B
If workbook A is Open, refresh data connections on workbook B
If workbook A is closed, open workbook A and refresh data connections on workbook B, then close workbook A.
Protect a certain worksheet on Workbook B
The code below works as intended in most scenarios when testing so far, but if someone else tries to open workbook B on their computer when someone else has Workbook A opened on another computer, it opens workbook A as a read-only file and keeps it open on their computer. I need it to close on their computer, and keep the initial one open that's on the other computer.
Public Sub RefreshPvt()
ThisWorkbook.Worksheets("Sheet1").Unprotect
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim wkb As Workbook
If IsFileOpen("S:\\Testing\Job Closeout Status Test.xlsx") Then
ThisWorkbook.RefreshAll
Else
Set wkb = Workbooks.Open(filename:="S:\\Testing\Job Closeout Status Test.xlsx")
ThisWorkbook.RefreshAll
wkb.Close SaveChanges:=False
End If
ThisWorkbook.Worksheets("Sheet1").Protect DrawingObjects:=True, Contents:=True, Scenarios:=True _
, AllowFormattingCells:=True, AllowFormattingColumns:=True, _
AllowFormattingRows:=True
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
Function IsFileOpen(filename As String)
Dim filenum As Integer, errnum As Integer
On Error Resume Next ' Turn error checking off.
filenum = FreeFile() ' Get a free file number.
' Attempt to open the file and lock it.
Open filename For Input Lock Read As #filenum
Close filenum ' Close the file.
errnum = Err ' Save the error number that occurred.
On Error GoTo 0 ' Turn error checking back on.
' Check to see which error occurred.
Select Case errnum
' No error occurred.
' File is NOT already open by another user.
Case 0
IsFileOpen = False
' Error number for "Permission Denied."
' File is already opened by another user.
Case 70
IsFileOpen = True
' Another error occurred.
Case Else
Error errnum
End Select
End Function
if you run ThisWorkbook.RefreshAll on workboook B in the immediate window does it work?
You could also make XLApp.Visible = true to see whether or not it's opening
I think you should be using something more like:
Dim pt As PivotTable
For Each pt In ActiveSheet.PivotTables
pt.RefreshTable
Next pt
To do the whole workbook you could use:
Sub AllWorkbookPivots()
Dim pt As PivotTable
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
For Each pt In ws.PivotTables
pt.RefreshTable
Next pt
Next ws
End Sub
Microsoft Office tracks those locks using files that are created in the same directory as the original file. The document filename.xlsx gets a temporary lock file: ~$filename.xlsx. If the document is in use, other user/macro opens the document as read-only. It's by design.
We might try to use Shared workbook feature of Excel, but there are some limitations.
For more detail information, please refer to the following link:
https://support.office.com/en-za/article/Use-a-shared-workbook-to-collaborate-79bd9dee-1aa3-49b5-bc27-a1ad28ffcbce
As mentioned here: https://social.technet.microsoft.com/Forums/ie/en-US/c1b179e1-ec4a-4ab9-abf4-21dc8b0c9326/vba-excel-to-excel-data-connection-it-opens-the-source-file-at-refresh?forum=excel
I am trying to schedule a task in Window's Task Scheduler that opens an excel file and auto run the macro in it.
The macro part is all done, but one problem I have is when the file is already open and the scheduled task runs. Whenever this happens, it will ask you if you want to reopen the file, if i accidentally click yes, which actually happened, then the data I was working on will all disappear.
So what I want is for the task to not run when file is open. Do I need to run a script? create a batch file with the code? If possible can you provide me a code that can do this as I am not familiar with another language aside from VBA
Note.
Just to clarify, I have a file that constantly pull data form Live Bloomberg. What I want to do is to save it as another workbook for reference everyday at 4:30pm. There is a few problem.
Here is how what I wrote in ThisWorkbook for easier understanding what I want to accomplish
Private Sub Workbook_Open()
Application.OnTime TimeValue("16:30:00"), "MyMacro"
End Sub
1)If I didn't open that excel that day, Workbook_Open() simply won't run.
2)Even if I did open the excel, if I close Excel before 4:30pm the macro won't run
So what I want is to have windows task scheduler constantly open the excel file for me that will always run on time regardless of what happens.
There are other problems too. I always write comments and stuff to the Live Data File, so if Task Scheduler tries to open the data file which in turn activating the Workbook_Open() while I am using it, a popup will come up asking if I want to reopen file. Of course I simply need to press "no" then the task will stop and everything is fine. But what if I wasn't there to press the button? Also on a few occasion I accidentally press "yes", which wiped out all the comments I wrote.
Therefore what I wanted to ask is that if The Live Data File is already open, simply make it so that the task in Task Scheduler won't run.
Have you considered using the Workbook.ReadOnly Property? This won't exactly tell you if the file is open but it will tell you if you have write-access. Try:
Public Sub OnlyRunWithWriteAccess()
Dim oBook As Workbook
Set oBook = Application.ActiveWorkbook
If Not oBook.ReadOnly Then
'Your processing code goes here...
End If
Set oBook = Nothing
End Sub
First of all thanks Steve S for your input.
I already did a workaround. Instead of having the LiveData file to run the macro, I put the macro on a clean excel template and have task scheduler open that file instead. This way is much more reliable and skips all the "Scripting in task scheduler" thing.
Here is my updated code:
'In ThisWorkbook
Public Sub Workbook_Open()
Run "AutoSaveAs"
End Sub
'In Module1
Public Sub AutoSaveAs()
Application.ScreenUpdating = False
Dim LDSP As String
Dim IsOTF
Dim LDS, TWB As Workbook
'Set LiveDealSheet file path
'Check if LiveDealSheet is already open
LDSP = "I:\LiveDealSheet\LiveDealSheet.xlsm"
IsOTF = IsWorkBookOpen(LDSP)
'Set quick workbook shortcut
Set TWB = ThisWorkbook
If IsOTF = False Then
Set LDS = Workbooks.Open(LDSP)
Else
Workbooks("LiveDealSheet.xlsm").Activate
Set LDS = ActiveWorkbook
End If
'Copy all data from LIVE Deals to TWB
LDS.Sheets("LIVE Deals").Cells.Select
Selection.Copy
TWB.Sheets(1).Cells.PasteSpecial (xlValues)
TWB.Sheets(1).Cells.PasteSpecial (xlFormats)
TWB.SaveAs FileName:="I:\LiveDealSheet\" & Format(Date, "yyyymmdd") & " LiveDealSheet", FileFormat:=52
If IsOTF = False Then
LDS.Close False
TWB.Close False
Else
TWB.Close False
End If
Application.ScreenUpdating = True
End Sub
Function IsWorkBookOpen(FileName As String)
Dim ff As Long, ErrNo As Long
On Error Resume Next
ff = FreeFile()
Open FileName For Input Lock Read As #ff
Close ff
ErrNo = Err
On Error GoTo 0
Select Case ErrNo
Case 0: IsWorkBookOpen = False
Case 70: IsWorkBookOpen = True
Case Else: Error ErrNo
End Select
End Function