Excel waits a long time to start saving the document - excel

When opening my sheet, I create a backup file of the current workbook almost without any delay.
When I close the file, another copy of the workbook is created also almost without any delay.
When saving the master file, Excel waits a long time (sometimes it takes several minutes) before saving.
The master file is not large, only 1.05Mb. I tried speedup solutions available on the net. Even tried reinstalling Excel.
This is the coding.
Private Sub Workbook_Open()
... ' perform some actions like setting NewName and ext
ActiveWorkbook.SaveCopyAs (NewName & " (backup)." & ext)
....
End Sub
Private Sub Workbook_Deactivate()
... ' perform some actions like setting NewName and ext
ActiveWorkbook.SaveCopyAs (NewName & " (backup)." & ext)
....
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If SaveAsUI Then Cancel = True 'Excel will close and handle saving itself.
If ActiveWorkbook.Saved Then Cancel = True ' Cancel saving when no changes were made
...
Application.EnableEvents = False
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.DisplayAlerts = False ' Make sure no close message pops up from the application
ActiveWorkbook.Save
Application.DisplayAlerts = True
ActiveWorkbook.Saved = True
.... ' Processing stuff amongst with resetting ScreenUpdating, EnableEvents and Calculation
Cancel = True ' Or it will fire twice for some reason
End Sub
Upon closing Excel I let it handle all the saving itself.
The workbook and copies are stored on a file server via a 1Gb network. The network isn't the problem, since the copies are saved very quickly. It is the master file that is saved sluggishly. It seems to be even slower when I work longer with the workbook.
I recently switched from Office 2007 to Office 2016 (=365). Before the switch there were no problems.

The Workbook_BeforeSave event runs every time the current workbook is saved. When it completes, the workbook is saved unless Cancel has been set to True (at any point in the subroutine). Setting Cancel = True stops the workbook from being saved when the subroutine finishes.
The problem is when you call the Save method within the Workbook_BeforeSave event, it immediately triggers the same event again, which then tries to save the workbook again and then triggers the event again. This is repeated until you reach the limit of the number of the nested sub-routines that can run simultaneously.
SaveCopyAs saves a copy of the workbook, which doesn't trigger the BeforeSave Event, so it just saves a copy of the workbook once quickly.
Maybe 2007 didn't allow this recursive calling of the Workbook_BeforeSave event or it had a smaller limit of number of nested sub-routines.
Setting Cancel to True doesn't stop the event in its tracks, it just stops Excel from saving the workbook again after the subroutine has finished. If your intention is to not manually handle the saving when there have been no changes (detected by SaveAsUI = True), then perhaps you should just exit the sub at that point:
If SaveAsUI Then Exit Sub
The subroutine will then stop without calling the save method, but the workbook will still be saved when the sub finishes, ending the recursive loop.

You can test whether the file has already been saved before firing the save event:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If SaveAsUI Then Cancel = True 'Excel will close and handle saving itself.
If ActiveWorkbook.Saved = False Then
Application.DisplayAlerts = False
Application.EnableEvents = False
ActiveWorkbook.Save
Application.DisplayAlerts = True
Application.EnableEvents = True
'Debug.Print "Fired"
End If
End Sub

After extensive testing I come to this conclusion: the difference between saving a copy or the master file is that when the master file is saved, also temporary files and cash(?) is processed. This leads to extra delay before saving a file. This is the only reason I can find that explains the difference in behaviour between saving a copy or a master file.

Related

How to run a macro in excel VBA only on "Save-as" but not on normal "Save"

I have a form for work that I update and email out daily. I open from one master form ("Passdown Report 3rd Shift"), and save-as individual copies separated by the date ("Passdown Report 3rd Shift 2022-01-19") before I leave each day.
The form is filled with formulas that auto-update based on the day and based off stimuli from the other worksheets in the workbook, so I added a macro to convert all formulas in the range to their values.
I want to run this macro before I save the form as the daily file, but not when I'm simply updating and saving the master file. Is that something I can do?
Run Macro Before Closing a Workbook
It is expected that you SaveAs as the backup.
Only when closing the backup, the IF(StrComp... will note a different file name, and your macro will run and the backup will be saved again before closing.
It is kind of clumsy, but it should ensure the safety of your original.
The problem with BeforeSave is that you could do If SaveAsUI = True Then but you could also accidentally do the SaveAs on the original and have it 'destroyed'. I consider it too risky.
Option Explicit
Private ClosingBackup As Boolean
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Const sFileName As String = "Passdown Report 3rd Shift.xlsm"
If Not ClosingBackup Then
With Me
' Compare if you're closing the original or the backup.
If StrComp(.Name, sFileName, vbTextCompare) <> 0 Then ' backup
MyMacro
ClosingBackup = True
' Here it will again call this sub but will exit because
' 'ClosingBackup' is set to True ('If Not ClosingBakup Then').
.Close SaveChanges:=True
'Else ' ClosingBackup = False i.e. closing the original; do nothing
End If
End With
'Else ' ClosingBackup = True; closing the backup which was saved; do nothing
End If
End Sub
You can use the function BeforeSave, on your ThisWorkbook.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If SaveAsUI then
'Your code
end if
End Sub
In the microsoft documentation is written on the popup of the SaveAs, this code will be executed and the flag SaveAsUI will be true.
https://learn.microsoft.com/en-us/office/vba/api/excel.workbook.beforesave
Note: You will need to make it an .xlsm file if you want your macro te be saved...

How to use excel after save event to run a power query query then save again

I have an excel Workbook that uses Power Query to populate a table. The query pulls information from multiple external Workbooks as well as a table in a Worksheet within the same Workbook.
The Worksheet in the same Workbook also stores changes to columns that are meant to be manipulated. The Worksheet in the same Workbook is part of a loop. It stores information that is pulled into the main table but also stores the changes made.
To make this work correctly, the Workbook needs to be Saved before the storage query runs. If a Save does not occur before running the query, the query will not contain the changes.
This is accomplished easily when clicking the save button. The following code works well:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Application.EnableEvents = False
ThisWorkbook.Save
ThisWorkbook.Connections("Query - Stored").Refresh
Application.EnableEvents = True
End Sub
This does not work when the workbook is closed and save is clicked after clicking the document close.
The BeforeSave event does not fire because it does not get a chance to. The document closes and when it is reopened it shows it as a crashed file and is listed in the recovery list.
Can anyone help me understand why and how to overcome it.
Since this is caused by an Excel crash while closing, it's possible that the Refresh gets messed up when Close is underway.
You could try executing the Refresh before Closing, like this
Private Closing As Boolean
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Closing = True
Application.EnableEvents = False
ThisWorkbook.Save
ThisWorkbook.Connections("Query - Stored").Refresh
Application.EnableEvents = True
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If Closing Then Exit Sub
Application.EnableEvents = False
ThisWorkbook.Save
ThisWorkbook.Connections("Query - Stored").Refresh
Application.EnableEvents = True
End Sub

Runtime error when using ActiveWorkbook.SaveCopyAs Filename

ActiveWorkbook.SaveCopyAs Filename: gives
Runtime error 1004
but hitting Debug>Run> Continue code runs as expected.
I have a macro enable Excel2016 spreadsheet. When updated and saved to PC I also wish to save a copy to my NAS. I have written code (see below) and used identical code, other than filename, for two other spreadsheets. These other two spreadsheets are saved as expected (i.e. to NAS and PC with no Runtime error))
Code as follows:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
'Saves the current file to a backup folder and the default folder
'Note that any backup is overwritten
Application.DisplayAlerts = False
ActiveWorkbook.SaveCopyAs Filename:="\\ReadyNasDuo\Dell\Excelbak\finance18_19.xlsm"
ActiveWorkbook.Save
Application.DisplayAlerts = True
End Sub
I would expect problem file to act like the other two. Anyone any ideas why it does not. Only differences are that problem file is a lot larger, is password protected, has link to another spreadsheet and has far more 'coding'(i.e. more macros and VBA)
You must also deactivate the events Application.EnableEvents = False otherwise your Save/SaveCopyAs will trigger another Workbook_BeforeSave event.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
'Saves the current file to a backup folder and the default folder
'Note that any backup is overwritten
Application.DisplayAlerts = False
Application.EnableEvents = False
ThisWorkbook.SaveCopyAs Filename:="\\ReadyNasDuo\Dell\Excelbak\finance18_19.xlsm"
'ActiveWorkbook.Save 'needed?
Application.EnableEvents = True
Application.DisplayAlerts = True
End Sub
Also I think you don't need ActiveWorkbook.Save because it will save at End Sub anyway as long as you don't set Cancel = True. The event is called BeforeSave not InsteadOfSave so the original save action will still happen when BeforeSave finished.
Note that ThisWorkbook and ActiveWorkbook are not the same. I assume that you meant to use ThisWorkbook which is the workbook this code is running in, while ActiveWorkbook is the one that has the focus (is on top) while the code is running.

Prevent Saving in excel couldn't be saved?

This may sound silly but I'm trying to prevent saving in Excel Workbook by using the code below in ThisWorkbook:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Cancel = True
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Application.ThisWorkbook.Saved = True
End Sub
However, after pressing Ctrl + s, and close the workbook, when reopening it, the code wasn't saved.
Any idea why this happen ?
This is a good thing - it means your code is working right. Your code prevented you from saving the workbook yourself. I have this in a couple applications I have made, the way around it is to make a sub as follows:
sub saveTheWB()
Application.EnableEvents = False
ThisWorkbook.Save
Application.EnableEvents = True
end sub
You have to run this sub every time you want to save.
That's right because the Workbook_BeforeSave event handler is firing and cancelling the save operation.
In the Immediate window of The IDE, run Application.EnableEvents = False before saving your workbook and it will save with the code.
Don't forget to run Application.EnableEvents = True after!

How to disable the save as prompt?

If IsWorkbookOpen("CONTRACT\CONTRACTLIST_Cement.xlsx") Then
x = 0
Else
Application.DisplayAlerts = False
ActiveWorkbook.Close savechanges:=True
Application.DisplayAlerts = True
End If
Hi, despite using the above code, the save as prompt still occasionally appears and affect the program. Does anyone know how to stop it completely? The problem is that after I click save as, it will alert me that it was still open.
Try below code
Its always good to explcilty refer the workbook rather than ActiveWorkbook
Sub test()
If IsWorkbookOpen("CONTRACT\CONTRACTLIST_Cement.xlsx") Then
x = 0
Else
Application.DisplayAlerts = False
ThisWorkbook.Save
ThisWorkbook.Close False
Application.DisplayAlerts = True
End If
End Sub
You can use Workbook_BeforeSave Event in the ThisWorkbook object to capture the user selecting SaveAs (or using the keyboard shortcut), which would result in the Save As prompt being displayed and the SaveAsUI being set to true. If SaveAsUI is true, this means the user is trying to save the file as something else, so you can then cancel the save As operation.
Open up the Visual Basic Window (Alt + F11) and put the following code in ThisWorkbook.
Disable Save As
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If (SaveAsUI = True) Then
MsgBox "Sorry. I can't have you saving this file as something else."
Cancel = True
End If
End Sub
You can delete the MsgBox line if you want; i put it there as an example if you wanted to notify the user that the function was disabled
To disable both the Save and Save As functionalities, you would remove the if statement and cancel the Save operation, regardless of if the Save as prompt is displayed.
Disable Save and Save As
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
MsgBox "Sorry. I can't have you saving this file at all."
Cancel = True
End Sub
If you just want to disable the Save operation, you would only need to look for the occurrence where the user is saving, but the SaveAsUI is not being displayed (i.e. user is simply saving the file).
Disable Save
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If (SaveAsUI = False) Then
MsgBox "Sorry. I can't have you saving any updates to this file."
Cancel = True
End If
End Sub
Finally, note that the user will still get a prompt to save if the user simply closes the file. The user won't be able to save and the file will close, but if you want the experience to be a bit cleaner, you'll need to make an additional change. When a user closes a file, Excel checks the ThisWorkbook.Saved variable to see if the file has been saved. If it is false, it will prompt the user to Save the file. To prevent this as well, we can set this boolean to true without saving, thus "tricking" Excel into thinking the file has been saved
Disable Save and Save As, including after User attempts to close file
Add the following code after your Workbook_BeforeSave code.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
ActiveWorkbook.Saved = True
MsgBox "Click OK to continue closing this file. Changes will not be saved."
End Sub

Resources