Prevent close during BeforeSave event - excel

Question:
A user attempts to close a file they've made changes to. A prompt comes up asking if they would like to save and they click 'Yes'. If there is code in the BeforeSave event that cancels the save, is there a way to also cancel the closing?
Background:
We make frequent use of "blank files", pre-formatted files with formulas and such that a user can open, enter data, and save under a new file name. It's that last step that caused problems. Users would save their data to the blank file, which meant we'd have to restore it to its original condition (clear out data, re-enter formulas that were deleted/overwritten, revert changes to formatting, etc.).
To prevent this, I added the following code to all blank files:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If instr(UCase$(ThisWorkbook.Name), "BLANK") <> 0 then
If SaveAsUI = False Then
MsgBox "This is the blank file. You can't save it. " _
& "Please choose 'Save As' and save with a new file name.", _
vbExclamation, "Can't Save Blank"
Cancel = True
End If
End If
End Sub
If the user tries to save data to a blank file, they'll get a message telling them they can't, and to use the Save As dialog instead. And if I need to make changes to the blank file, I can use the Save As dialog to save it using the same file name.
The problem lies when I make changes to a blank file and try to close that file. The prompt will come up asking me if I want to save my changes. Not thinking about it, I'll click 'Yes'. Then my code will be triggered preventing a save and notifying me, as intended. But when I click 'OK' on my message, the file immediately closes without saving changes.
What I'd like is some way to prevent the file from closing when saving has been canceled.

I took the code from there and modified it.
save as dialog excel code
I hope it solves your problem or at least it will after some small changes.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim varResult As Variant
Dim ActBook As Workbook
'displays the save file dialog
varResult = Application.GetSaveAsFilename(FileFilter:= _
"Excel Files (*.xlsx), *.xlsx", Title:="Save As", _
InitialFileName:=Application.ActiveWorkbook.Path)
'checks to make sure the user hasn't canceled the dialog
If varResult <> False Then
ActiveWorkbook.SaveCopyAs Filename:=varResult '_
'FileFormat:=xlWorkbookNormal
Exit Sub
End If
End Sub
' No it is just in case the user doesn't want to save the file and cancels the first dialog
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If InStr(UCase$(ThisWorkbook.Name), "BLANK") <> 0 Then
If SaveAsUI = False Then
MsgBox "This is the blank file. You can't save it. " _
& "Please choose 'Save As' and save with a new file name.", _
vbExclamation, "Can't Save Blank"
Cancel = True
End If
End If
End Sub
Edit:
After pressing closing button:
Everytime changes have been made a window to 'save as' pops up and after saving a copy it just closes, no more poping up windows afterwards
If no changes have been made it just closes the workbook
the code:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim varResult As Variant
Dim ActBook As Workbook
If InStr(UCase$(ThisWorkbook.Name), "BLANK") <> 0 Then
If Not ThisWorkbook.Saved Then
'displays the save file dialog
varResult = Application.GetSaveAsFilename(FileFilter:= _
"Excel Files (*.xlsm), *.xlsm", Title:="Save As", _
InitialFileName:=Application.ActiveWorkbook.Path)
'checks to make sure the user hasn't canceled the dialog
If varResult <> False Then
ActiveWorkbook.SaveCopyAs Filename:=varResult '_
'FileFormat:=xlWorkbookNormal
ThisWorkbook.Saved = True
Exit Sub
Else
ThisWorkbook.Saved = True
End If
End If
End If
End Sub
' Just in case the user presses save in options
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If InStr(UCase$(ThisWorkbook.Name), "BLANK") <> 0 Then
If SaveAsUI = False Then
MsgBox "This is the blank file. You can't save it. " _
& "Please choose 'Save As' and save with a new file name.", _
vbExclamation, "Can't Save Blank"
Cancel = True
End If
End If
End Sub
Final version
After pressing closing button:
Everytime changes have been made a window asking if you want to save changes appears (one can cancel it, say no or yes)
If yes was chosen (default button) a 'save as' window pops up and after saving a copy it just closes, no more poping up windows afterwards
If no changes have been made it just closes the workbook
The code:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim varResult As Variant
Dim ActBook As Workbook
Dim MsgBoxAnswer As Variant
If InStr(UCase$(ThisWorkbook.Name), "BLANK") <> 0 Then
If Not ThisWorkbook.Saved Then
MsgBoxAnswer = MsgBox("Do you want to save changes?", vbYesNoCancel + vbExclamation + vbDefaultButton1, "Microsoft Office Excel")
If MsgBoxAnswer = vbYes Then
MsgBox "This is the blank file. Save it with a new file name.", _
vbExclamation, "Can't Save Blank"
'displays the save file dialog
varResult = Application.GetSaveAsFilename(FileFilter:= _
"Excel Files (*.xlsm), *.xlsm", Title:="Save As", _
InitialFileName:=Application.ActiveWorkbook.Path)
'checks to make sure the user hasn't canceled the dialog
If varResult <> False Then
ActiveWorkbook.SaveCopyAs Filename:=varResult '_
'FileFormat:=xlWorkbookNormal
ThisWorkbook.Saved = True
Exit Sub
Else
ThisWorkbook.Saved = True
End If
ElseIf MsgBoxAnswer = vbNo Then
ThisWorkbook.Saved = True
ElseIf MsgBoxAnswer = vbCancel Then
Cancel = True
End If
End If
End If
End Sub
' Just in case the user presses save in options
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If InStr(UCase$(ThisWorkbook.Name), "BLANK") <> 0 Then
If SaveAsUI = False Then
MsgBox "This is the blank file. You can't save it. " _
& "Please choose 'Save As' and save with a new file name.", _
vbExclamation, "Can't Save Blank"
Cancel = True
End If
End If
End Sub

Related

Set password for open by VBA instead of built-in feature

I have a previous topic about setting password for another workbook. The other workbook is named "Sample.xlsm"
Protect closed workbook with password
Now I need to make the user input the password from the Sample.xlsm itself and at the same time to prevent the user from changing the password
I used this
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Application.DisplayAlerts = False
If SaveAsUI Then MsgBox "SaveAs Feature Disabled", vbExclamation: Cancel = True
Application.DisplayAlerts = True
End Sub
But this seems not enough from preventing the user to save the workbook with another name.
To force only saving to a specific location:
This is the code that should stop most attempts at saving:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Application.EnableEvents = False
Cancel = True
Call MySaveCode
BackToExcelSave:
Application.EnableEvents = True
End Sub
Then you have to add code for your save, and avoid triggering excels' default save routine:
Sub MySaveCode()
On Error GoTo ReEnable ' Use On Error in case they cannot save to specified location/filename
Application.EnableEvents = False ' turn off excel default action (Workbook_BeforeSave)
Dim Path As String
Dim FileName As String
Path = "C:\Users\SeanC\Documents\Excel\"
FileName = "MyFixedFilename.xlsm"
Application.DisplayAlerts = False 'Optional. Suppresses default excel messages
ThisWorkbook.SaveAs Filename:= _
Path & FileName, _
FileFormat:=xlOpenXMLWorkbookMacroEnabled, _
CreateBackup:=False, _
Password:="P#$$w0rd"
MsgBox "Saved as: " & ThisWorkbook.FullName 'Also Optional
ReEnable:
Application.DisplayAlerts = True 'Optional
Application.EnableEvents = True
End Sub

excel vba saveasui file path

I have created a template for registration of changes. These are the requests and further administration in the process. I have a code in this template to save the file as an excel macro enabled workbook, always. The problem with this code is that i can't define a specific folder to save the documents. In all cases the save as dialog box will pop up and the user must be able to define their own file name. I want to define the path for all the users. Does anyone know how to add a file location (path) in this macro in order to make it work?
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim FileNameVal As String
If SaveAsUI Then
FileNameVal = Application.GetSaveAsFilename(, "Excel Macro-Enabled Workbook (*.xlsm), *.xlsm")
Cancel = True
If FileNameVal = "False" Then 'User pressed cancel
Exit Sub
End If
Application.EnableEvents = False
If Right(ThisWorkbook.Name, 5) <> ".xlsm" Then
ThisWorkbook.SaveAs Filename:=FileNameVal, FileFormat:=xlOpenXMLWorkbookMacroEnabled
Else
ThisWorkbook.SaveAs Filename:=FileNameVal, FileFormat:=xlOpenXMLWorkbookMacroEnabled
End If
Application.EnableEvents = True
End If
End Sub
Thanks in advance.
Kind regards,
Remco H.
If you wish to generate a unique filename, you could use something like the following function:
Function NextFileName(basename As String) As String
Dim followup As Integer
Dim pathname As String
pathname = "C:\Temp\Temp\" ' Include the trailing path separator so that we don't have to do it later
followup = 1
Do
NextFileName = pathname & basename & "-" & followup & ".xlsm"
If Dir(NextFileName) = "" Then Exit Function
followup = followup + 1
Loop
End Function
You could then call it from your main code as
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim FileNameVal As String
If SaveAsUI Then ' <-- Exclude the IF statement if you want EVERY save to have a new follow up number
' rather than just "Save As" saves
Application.EnableEvents = False
'Generate the filename
FileNameVal = NextFileName(Format(Now, "yymmdd"))
ThisWorkbook.SaveAs Filename:=FileNameVal, FileFormat:=xlOpenXMLWorkbookMacroEnabled
'Maybe advise the user that the save has happened, and where it went to
MsgBox "Spreadsheet saved as " & FileNameVal
Cancel = True
Application.EnableEvents = True
End If
End Sub

Excel 2016 VBA force save to .xlsm - How to save the template?

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim fname As Variant, DateTime As String, myInitialFilename As String
On Error GoTo ErrorHandler
SaveAsUI = True
If SaveAsUI Then
Cancel = True 'Cancel the original SaveAs
DateTime = "_" & Format(Now(), "yyyy_mm_dd_hhmmss") '= " [yyyy_mm_dd]"
'DateTime = " [" & Format(Now(), "yyyy_mm_dd hhmm_ss") & "]" '= " [yyyy_mm_dd hhmm_ss]" (use instead if you want time in the name)
myInitialFilename = "Quote" 'EDIT THIS
'Get filename (with path) for saving
fname = Application.GetSaveAsFilename(InitialFileName:=myInitialFilename & DateTime, fileFilter:="Excel Marcro-Enabled Workbook (*.xlsm),*.xlsm")
If fname = False Then Exit Sub 'Exit if user hit Cancel
Application.EnableEvents = False 'Prevent this event from firing
ThisWorkbook.SaveAs Filename:=fname, FileFormat:=52
'52 = xlOpenXMLWorkbookMacroEnabled = xlsm (with macro's in 2007-2010)
Application.EnableEvents = True 'Re-enable events
End If
Exit Sub
ErrorHandler:
Application.EnableEvents = True
MsgBox "An error occured during save." & Err.Number, vbCritical, "Error"
End Sub`
I have written a bit of VBA code to force a save or save-as to be the file type .xlsm, which works fine. However, I can't seem to save the template file with the VBA code in it because of the code itself forcing the .xlsm save.
I have a template saved without the code, but as soon as I add the code, obviously I can no longer save as xltm, since the code pushes to save as xslm. Looking for a best practice solution to save my template!
Thanks,
Kathy B.
Any changes within the file will either make it always save as xltm, or always as xlsm. So you want a flag stored in a different file, which defaults to false. This way, when you want to edit your template, you can turn it on and save your changes, but in normal usage, it will save as .xlsm.
If you do not overwrite the SaveAsUI-Flag with true
you can save the file as Template when you work on it.
If you create a new File form the Template the
SaveAsUI-Flag will be true and then your code forces
to keep the macros.

forbid saving as in a given folder using excel VBA

I have created a folder containing many .xls and .xlsm sheets, this folder will be distributed to many people in the company, in order not to alter the integrity of the sheets in the folder I want to disable saving any files in this folder, all filles saved will have to be "saved as" in a location different than the folder called project.Here is what have found so far.
Cheers
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
' Following line will prevent all saving
Cancel = True
' Following line displays the Save As Dialog box
If SaveAsUI Then SaveAsUI = True
' How do I forbid the folders path ???
End Sub
I've come up with one way of doing it. Maybe someone can give you a better answer.
It will save a file to your default location which is set to be C:\MyFiles and show a MessageBox after with the path to the file.
Only use this code if you do not want to ask the user where to save the file and save it in a static location then notify him/her of the location the file was saved to.
The below code goes in here (ThisWorkbook Object Module)
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If SaveAsUI Then
Cancel = True
Else
Dim path As String
path = "C:\MyFiles\"
If Len(dir(path, vbDirectory)) = 0 Then
MkDir path
End If
Me.SaveAs Filename:=path & Me.Name, _
FileFormat:=xlOpenXMLWorkbookMacroEnabled, CreateBackup:=False
MsgBox "This file has been saved in " & path & Me.Name
Cancel = True
Exit Sub
End If
End Sub
update!
If all your users are on Windows 7 than you can change the path to
path = "C:\Users\" & Environ$("username") & "\Desktop\"
This will go to each user's desktop regardless of their username. The Environ$("username") function returns currently logged in username.
This version saves to the User Desktop regardless of the Windows O/S version
It also disables Events so that the code doesn't call itself recursively.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim ws As Object
Set ws = CreateObject("WScript.Shell")
If ThisWorkbook.Saved Then
Application.EnableEvents = False
ThisWorkbook.SaveAs ws.specialfolders("Desktop") & "\" & ThisWorkbook.Name
MsgBox ThisWorkbook.Name & " saved to " & ws.specialfolders("Desktop")
Application.EnableEvents = True
Else
MsgBox "workbook has not been saved before", vbCritical
Cancel = True
End If
End Sub

Force Save as XLSM While Maintaining File Structure

So I am working with a XLTM file, and I want the user to make sure they save as XLSM. When they click "Save," this works fine, but I find when they click "Save As," the file is saved as "*.xlsm.xlsm". I am a little lost with how to make sure that the user saves as XLSM, while keeping the file name as "filename.xlsm" and not "filename.xlsm.xlsm".
'Action makes sure the user saves as XLSM file type.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim FileNameVal As String
If SaveAsUI Then
FileNameVal = Application.GetSaveAsFilename(, "Excel Macro-Enabled Workbook (*.xlsm), *.xlsm")
Cancel = True
If FileNameVal = "False" Then 'User pressed cancel
Exit Sub
End If
Application.EnableEvents = False
ThisWorkbook.SaveAs Filename:=FileNameVal & ".xlsm", FileFormat:=ThisWorkbook.FileFormat
Application.EnableEvents = True
End If
End Sub
I thought the problem may have been writing ".xlsm" in:
ThisWorkbook.SaveAs Filename:=FileNameVal & ".xlsm", FileFormat:=ThisWorkbook.FileFormat
However, without ".xlsm" written there, I find the file instead saves as a bad file suffix. (E.g., if my XLTM file is called Template(File001).xltm, and the user opens a new template file, it will save as Template(File001)1 (believing that "1)1" is the file type).
It may be the structure of my code, so I need direction in how to revise it.
The problem appeared to have existed because the template would name the file "Template(1)1" prior to it actually being saved initially. This changes the way that Excel saves the file, so the easiest way to contrast between this initial save and further saves (that already contain a file extension) was to use an if-then statement to judge whether an extension exists already.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim FileNameVal As String
If SaveAsUI Then
FileNameVal = Application.GetSaveAsFilename(, "Excel Macro-Enabled Workbook (*.xlsm), *.xlsm")
Cancel = True
If FileNameVal = CStr(False) Then 'User pressed cancel
Exit Sub
End If
Application.EnableEvents = False
If Right(ThisWorkbook.Name, 5) <> ".xlsm" Then
ThisWorkbook.SaveAs Filename:=FileNameVal & ".xlsm", FileFormat:=xlOpenXMLWorkbookMacroEnabled
Else
ThisWorkbook.SaveAs Filename:=FileNameVal, FileFormat:=xlOpenXMLWorkbookMacroEnabled
End If
Application.EnableEvents = True
End If
End Sub

Resources