Excel VBA Read Only supersedes BeforeSave - excel

I have code that incorporates business logic for saving documents (Excel 365) to ensure proper naming convention, file locations etc etc as a Sub Workbook_BeforeSave
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Cancel = True ''Cancels the Save from the button push or Ctrl+S
Application.EnableEvents = False
'' code code code
Application.EnableEvents = True
End Sub
The problem is that if the file is opened as Read-Only (as most will be) Excel will prompt that "the file is Read-Only" (pic a) and go to the Save As screen in the File Ribbon (pic b). The Workbook_BeforeSave sub won't kick in until the SAVE button is pressed. It also won't move off this screen even after the sub has run.
Is there any way to either:
Get in front of the Read-Only prompt ... or
Write some code to move off the Save As screen?
MS Read-Only promt (pic a)
Save As Screen (pic b)
Huge thanks in advance!

This is not a perfect approach but try this.
This will cancel the save completely even after pressing the Save button, you can add your own save code.
Edit: Just realized that the code below does not stop the Read Only Alert, but when you click Save it cancels the Save and Closes the Save As Menu. However, when they use Ctrl+S the Send Keys {ESC} triggers a Ctrl+ESC which opens the Star Menu...
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
'Disable Read Only Alert
Application.DisplayAlerts = False
'Disable Events
Application.EnableEvents = False
'Cancel Save
Cancel = True
'Do whatever code you need in here
'
'Mark Workbook as Saved, allowing for the file to close without an alert even if not saved
ThisWorkbook.Saved = True
'Send Escape Key to leave Save As Menu
Application.SendKeys "{ESC}", 1
'Enable Events
Application.EnableEvents = True
'Enable Alerts
Application.DisplayAlerts = True
End Sub

Related

Detect if Save event is triggered manually or by autosave

I'm using a small piece of code to export the VBProject components before saving the workbook.
Private Sub App_WorkbookBeforeSave(ByVal Wb As Workbook, ByVal SaveAsUI As Boolean, Cancel As Boolean)
If Wb.HasVBProject Then
If Wb.VBProject.Protection = vbext_pp_none Then
If vbYes = MsgBox("Do you want to export the VBProject components?", vbYesNo) Then
ExportWB Wb ' call a function to export the data
End If
End If
End If
End Sub
This code is working fine, but if the Autosave is on the user (me) is asked every few second if it wants to export the project.
I can check if Autosave is On or Off with Wb.AutoSave, but is there a way to check if the event was triggered manually or by Autosave, in order to run the code only when someone require a save, not for the Autosave events?
Vincent
Using ThisWorkbook.AutoSaveOn = False, the effect should be gone. You can place this line e.g. into ThisWorkbook's event Private Sub Workbook_Open.
You can get the info about if AutoSave is currently enabled for this file, from ThisWorkbook.AutoSaveOn (returns True for enabled, or False for disabled).

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

How to prevent the user from saving a file to any directory except one specific location?

I'm working on code (Excel 2016) to prevent the user from saving a file to any directory except one specific location. I'm using the BeforeSave event as follows:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim NamePath As String
On Error GoTo Final
' If Saving Then Exit Sub
If SaveAsUI = True Then
Cancel = True
Application.EnableEvents = False
NamePath = Application.GetSaveAsFilename(InitialFileName:=ActiveWorkbook.Name, FileFilter:="Excel Files (*.xlsm), *.xlsm")
If NamePath = "False" Then Exit Sub
If InStr(1, NamePath, "H:\SSV\WORK\Workcenter Safety Modification Tracking Files", vbTextCompare) = 0 Then
MsgBox "You cannot save to another directory."
GoTo Final
Else
Me.SaveAs NamePath
GoTo Final
End If
End If
Final:
Application.EnableEvents = True
End Sub
When I select File from the ribbon bar and then Save As, I end up here:
When I click the Save button my code assumes that I haven't already entered a new filename, so it prompts for a Save As name and location. This works, as long as the user isn't using File|Save As. Using a Save As Button from a Quick Launch or customized ribbon works.
My problem is that using File|Save As doesn't trigger the BeforeSave event until after you enter the new filename and/or select a new location and click the Save button on the File|Save As screen. In the File|save as screen, I can already select one or both of these, but the BeforeSave event has no knowledge of this, it's firing just as if I had clicked on a Quick Launch button and hadn't already entered the new name or selected a new location. The user enters the new file name/location, clicks Save and is prompted again for a new file name/location.
I'm looking for one of two solutions:
A different way to limit where a user can save a file.
A way to pass the file name/location from the above File|Save As screen into the BeforeSave event.
I may be wrong but when they select the new location it might change the current working directory - in which case using CurDir may help
Application.GetSaveAsFilename() will return save as file path which you selected in File-> Save As.
C# code is below
Object obj = Application.GetSaveAsFilename();
if(obj != null)
{
string filePath = obj.ToString();
}
In VBA
Application.GetSaveAsFilename
Put a button on the sheet and force the user to use that exclusively.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If not DoingSave then
Msgbox("You must save using the button")
Cancel = True
End If
End Sub
When the user saves using the button, set DoingSave to True before saving and set it to False afterward.

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

change the "Cancel" text on SaveAs Dialog box in excel VBA to "Review"

Is there a way to change the "Cancel" text on SaveAs Dialog box in excel VBA to "Review"?
I have no idea how to change the default Yes, No, Cancel setting.
Will appreciate your input.
No
To do this you would need to:
Intercept the SaveAs with a Workbook Event
Exit if the user was using Save rather than SaveAs
Provided your own customised SaveAs UserForm (UserForm1.Show below as a sample line to an un-designed form)
Note that Events should be disabled to prevent your UserForm Save from re-calling the Workbook_BeforeSave Event
All up - I'd stay with the defaults!
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
'exit on Save
If Not SaveAsUI Then Exit Sub
Application.EnableEvents = False
Cancel = True
UserForm1.Show
Application.EnableEvents = True
End Sub

Resources