I have an Excel file, PlannerTool which keeps prompting to save the file when closing, even when it has been saved 2 seconds ago. This is probably due to some volatile code. So I thought I would disable the prompt when the file had been saved within a certain time window. However when I do so, Excel refuses to completely shutdown. It will close the workbook, but a grey screen will remain. See screenshot below.
The code I use to deny the prompt is taken from
VBA workbooks.Close without being prompted to if the user wants to save?
Complete code used provided below:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Application.EnableEvents = False
Dim SaveTime As Date
Dim CurrentTime As Date
Dim TimeDifference As Long
SaveTime = ThisWorkbook.BuiltinDocumentProperties("Last Save Time")
CurrentTime = Now
TimeDifference = DateDiff("s", SaveTime, CurrentTime)
'Gets the time difference between closing and saving in seconds
If TimeDifference <= 10 Then 'Saved less than 10 seconds ago so deny prompt
Application.DisplayAlerts = False 'Code gotten from StackOverflow Question
ThisWorkbook.SaveAs Filename:="PlannerTool", FileFormat:=xlOpenXMLWorkbookMacroEnabled, ConflictResolution:=xlLocalSessionChanges
ThisWorkbook.Saved = True 'Tweaked to fit saving format needs
ThisWorkbook.Close SaveChanges:=False
Application.DisplayAlerts = True
End If
Application.EnableEvents = True
End Sub
If the VB Editor is open when closing the workbook, the editor will remain open and display the RibbonX_Code Module. The VBA project containing the workbook PlannerTool and code are no longer displayed in the Project Tree, indicating that they are indeed closed. No difference when I have 1 or multiple workbooks opened, these stay displayed in the tree when I close PlannerTool. Can anyone tell me why Excel won't close properly?
I can replicate this behavior locally, and it appears that calling ThisWorkbook.Close is the issue. If you open a workbook and then use the Excel menu to close it, (File -> Close), it does the same thing as your code. In the "manual" case, Excel holds the application open because you opted not to close Excel - just the open workbook.
This should work as intended if you manually check to see if Excel should be closed.
If TimeDifference <= 10 Then 'Saved less than 10 seconds ago so deny prompt
Application.DisplayAlerts = False 'Code gotten from StackOverflow Question
ThisWorkbook.SaveAs Filename:="PlannerTool", FileFormat:=xlOpenXMLWorkbookMacroEnabled, ConflictResolution:=xlLocalSessionChanges
ThisWorkbook.Saved = True 'Tweaked to fit saving format needs
ThisWorkbook.Close SaveChanges:=False
Application.DisplayAlerts = True
If Application.Workbooks.Count = 0 Then
Application.Quit
End If
End If
I'd suggest this rather than forcing the application itself to close, as the user may have other documents open in Excel.
Related
I created a macro that automatically opens a "raw" workbook file, does some calculations/manipulations, then saves it in another location. However, sometimes the original "raw" data file has corrupted characters that causes excel to get stuck while opening the file (even if done manually) -- it will just keep the opening file dialog open, with a full status bar, but will never actually proceed to opening the file or present an error. So, when we run the macro, it runs forever, trying to open the file but it is unable to proceed because the file never opens.
I am trying to add a timer to the function so that "if rawdata.xlsx takes longer than 5 minutes to open, cancel and stop procedure."
So far, I'm trying the following (file names have been changed for placeholders):
Sub wbprocess()
Dim Start, MaxTime, OpenStatus
OpenStatus = False
Start = Timer
MaxTime = 300 '(seconds)
Do While Timer < Start + MaxTime Or OpenStatus = False
Dim wb As Workbook
Set wb = Workbooks.Open(input file here)
' calculations and rest of code here
wb.SaveAs Filename:=output file here, FileFormat:=xlOpenXMLWorkbook
wb.Close
OpenStatus = True
Loop
End Sub
But, it won't leave the while loop until the max time has been reached, even if the file takes less than the allotted 5 minutes to open. What would be the correct logic to make it leave the while loop, and continue the calculations once the file has opened?
Scenario:
User is running a macro-enabled Excel Workbook. User clicks a link on a UserForm that launches another macro-enabled Excel Workbook that also has user forms. The second Workbook is then closed using the following code:
Private Sub btnExit_Click()
'Check if other Excel files are open before quitting the application
If Workbooks.Count = 1 Then
Application.Quit
Else
ThisWorkbook.Close
End If
End Sub
and...
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim intResponse As Integer
If MsgBox("Are you sure you would like to exit the calculator?", vbYesNo + vbQuestion) = vbNo Then
Cancel = True
End If
ThisWorkbook.Saved = True
End Sub
Upon closing of the second Workbook (ThisWorkbook.Close), the original Workbook remains open, however, the vbModeless UserForm that was previously visible has been killed. It might also be pertinent to mention that the second Workbook's forms are Modal.
If the second Workbook is closed using the Excel exit button in the upper right corner, this problem does not occur.
Does anyone know why this is happening? Is it because code execution for Excel.Application is ceased when the Workbook is closed programmatically? Could it be due to the difference in form modes? Is there a work-around other than putting a button on the original Workbook in a Sheet to re-launch the UserForm?
Many thanks for any assistance with this issue!!
CiViCChiC79
This is what is happening:
Assuming that both workbooks are in the same Excel Application, Application.Quit would close them both.
ThisWorkbook.Close will close the workbook, in which the code is present.
Thus, concerning your question - you are not closing the second workbook with ThisWorkbook.Close, but you are closing the workbook, which has the btnExit button, on which you have clicked. I guess that both the workbooks are quite similar and you are mistaken which one you are closing?
Changing the second Workbook's form containing the Exit button to vbModeless fixed the problem!!!! Yay!!!!!
I have an excel workbook that I download using simple HTML portal that I coded. When I download the workbook it automatically renames it as "myWorkbook (27)" or whatever number of times it has been put in the downloads folder.
I have some code that changes the Save As location of the workbook to the original location that it was downloaded from. See:
Private Sub Workbook_Open()
Application.DisplayAlerts = False
'Check to see if another workbook with the same name is open -- close if so.
If IsOpenWorkbook("myWorkbook.xlsm", True) Then
Workbooks("myWorkbook.xlsm").Close saveChanges = False
End If
ThisWorkbook.SaveAs Filename:="\\999.9.9.99\folder\anotherFolder\myWorkbook.xlsm"
Application.DisplayAlerts = True
End Sub
This has worked fine for almost a month but recently has been performing erratically. When I first download the sheet, it has the regular "Enable Editing" prompt which I accept. After accepting, the name of the workbook changes suggesting the code as run, but then has another "Enable Editing" prompt which, if I accept, will crash Excel.
Any insights appreciated.
I have looked everywhere to get an answer to this and can't figure it out. I'm looking for a way to close and save a workbook automatically at midnight every night because it has important information that people keep losing because they don't save it. I've got the closing and saving part down, if I manually click the X to close Excel, but I can't get it to do it at a predetermined time. I've used Application.OnTime without any success. Here is the code that I'm using to close and save the workbook. I just need the code to have it run at midnight if the workbook is still open.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Sheet1.Activate
Sheet1.Range("AB18:AD18").Select
Selection.ClearContents
ActiveWorkbook.Save
End Sub
I had trouble referencing the Worksheet .CodeName property but not with the Worksheet .Name property.
Module1 code sheet
Option Explicit
Sub ScheduleClose()
Application.OnTime Now + TimeSerial(0, 0, 4), "Kamikaze"
End Sub
Sub Kamikaze()
Debug.Print "boom"
Application.DisplayAlerts = False
With ThisWorkbook
.Worksheets("Sheet1").Activate
.Worksheets("Sheet1").Range("AB18:AD18").ClearContents
.Save
.Close savechanges:=False
End With
End Sub
Of course, the workbook must be already saved (i.e. not Book1) since no name is provided but a Workbook.SaveAs method could be used if the workbook habitually is not already saved.
This will also leave 'orphaned' VBA projects within the Excel application 'instance'. VBA cannot kill itself as it has to be running to complete the command.
I'm having serious trouble solving this issue:
I have an Excel Workbook (2010 or later) with a Macro that HAS TO run BeforeClose. It deletes internal data and saves this change: (no problem so far)
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim xlSheet As Worksheet
For Each xlSheet In Sheets
If xlSheet.Name = "internalDataSource" Then
MsgBox "Internal data will be deleted from the workbook. Changes are saved."
Application.DisplayAlerts = False
xlSheet.Delete
ThisWorkbook.Save
Application.DisplayAlerts = True
End If
Next xlSheet
End Sub
My Problem:
the user should be able to change something. Now if the user changes something he usually gets asked, if he wants to save the changes. In this version there is no choice, but saving his changes. currently they are always saved.
How can I get the user to be able to say "No, don't save my changes." but still run the macro and save the deletion of internal data afterwards?
I'm desperately looking for a VBA-command to revert all changes to the last saved state. Then I would simply run the Macro from above and save my deletion.
Thanks for any help I get!
This could be done by saving a copy of the workbook each time a normal save is done, move the internal data to the copy, and rename the copy as the original. There are few options for how to do this specifically, I'll post some suggestions here to flush out my answer:
Saving a copy could be placed in the Workbook_BeforeSave event.
Renaming the copy to the original could be done in the Workbook_BeforeClose procedure you have listed here.
To run a messagebox past the user, you may consider editing the MsgBox you have listed to something like:
If (MsgBox("You are attempting to exit." & vbNewLine _
& "All changes since the last save will be lost." & vbNewLine _
& "Okay to proceed?", 308) = vbNo) Then
Cancel = True
End If
Of course, not "all changes since the last save will be lost" because your internal data will be saved.