I am trying to create a macro that will give me a message box before closing Excel to ask if I want to save changes. When I select No from the message box the message pops up again, then the 2nd time that I chose No it does close.
I don't know very much about VBA programming, I just try to record macro's then edit them slightly. I also search online and copy paste. This is how I put together this code below but obviously something is wrong. (although it works)
I wonder if someone could advise me what needs to be changed in this code.
Any help appreciated,
Thanks
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim answer As String
Dim question As String
Dim OrigName As String
question = "Do you want to save Changes?"
answer = MsgBox(question, vbYesNoCancel)
If answer = vbCancel Then
Exit Sub
End If
If answer = vbNo Then
ActiveWorkbook.Close SaveChanges:=False
End If
If answer = vbYes Then
ActiveWorkbook.Save
ActiveWorkbook.SaveAs ("C:\Users\me\Documents\reports\Backup\" + ActiveWorkbook.Name & Format(Now(), "DD-MMM-YYYY hh-mm") & ".xlsm")
Exit Sub
End If
End Sub
Try this:
You're already closing the workbook, so there's no need to Close it again in your code. Just 'trick' Excel to think changes are saved with ThisWorkbook.Saved = True (Note: This only tells Excel that the changes were saved - it doesn't actually save them) and it won't prompt you to save changes.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Select Case MsgBox("Do you want to save Changes?", vbYesNoCancel)
Case vbCancel
Cancel = True
Case vbNo
ThisWorkbook.Saved = True
Case vbYes
ThisWorkbook.Save
ThisWorkbook.SaveAs ("C:\Users\me\Documents\reports\Backup\" + ActiveWorkbook.Name & Format(Now(), "DD-MMM-YYYY hh-mm") & ".xlsm")
End Select
End Sub
And using ThisWorkbook in your case would be a better object rather than using ActiveWorkbook.
Related
I am have limited experience in coding in VBA and have implemented some code into an excel workbook, for which I take no credit for and which I obtained via the web, so all credit to the original creator. The code forces the user to save the workbook as .xlsm. The code works fine, as shown, with a small niggle.
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")
MsgBox (FileNameVal)
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
The niggle is that in selecting File/SaveAs, the UI presents the SaveAs dialogue box in which I type the new filename. This then creates a further SaveAs dialogue box with input for the filename again, but the inserted filename is the original current filename not the new one entered in the previous step. It seems the new entry is not carried over to the following dialogue box. Not a big issue, just more of a niggle. Is there any way to correct this please?
I had the same need with a Word Document which needed to be forced to save as a .docm. This was achieved in a different manner and all credit goes to David Zemens as answered in this post Word VBA force save as .docm. This works really well for my need. I was wondering if this type of method could be used in Excel and if so what would need to change?
Any help would be appreciated, thanks in advance.
zump
I have code, that only runs when a user chose "Save As". To do that and getting the new name of the file I'm using the Application.GetSaveAsFilename function.
The problem I came across was a type mismatch while checking if the user clicked on Cancel when he did not do that.
Line that threw the error when Cancel was not clicked: If saveName = False Then Exit Sub
My working code:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If Not SaveAsUI Then Exit Sub
Cancel = True
'other variables
Dim saveName As String
saveName = Application.GetSaveAsFilename(filefilter:="Microsoft Excel Files (*.xlsm), *.xlsm", Title:="Save as Microsoft Excel Macro-Enabled Worksheet")
On Error GoTo RunTime13
If saveName <> False Then
On Error GoTo 0
'other code
ThisWorkbook.SaveAs Filename:=saveName, FileFormat:=52
End If
Exit Sub
RunTime13:
If Err.Number = 13 Then Resume Next
End Sub
What am I doing wrong, that I have to work around the Cancel button like this?
Edit:
I chose Dim saveName As Variant to be able to use If saveName = False Then Exit Sub
As Vityata mentioned I am in Germany and thus could have run into problems with the language, fortunately for me Vityata reminded me of the problem because I am in fact using Excel in English, but not all of my colleagues are, so my accepted answer might not have worked when they were using the workbook.
As you've declared SaveName as a string, you need to check for "False", not False.
If saveName <> "False" Then
OP, I have some news for you - you are in Germany and thus I am about 99% sure you are using German Excel.
There the VBA is a bit translated, thus the saveName is translated to Falsch and not False as in the rest of the world. E.g. CStr(False) returns Falsch.
In your code write either of these three:
If saveName <> "Falsch"
If saveName <> False
If Len(saveName) <> 6
Here's another approach:
Dim vSaveName As Variant
vSaveName = Application.GetSaveAsFilename(filefilter:="Excel Files (*.xlsm), *.xlsm", _
Title:="Save as Macro-Enabled Worksheet")
If TypeName(vSaveName) = "Boolean" Then Exit Sub
'' otherwise continue with save...
The only time vSavename is a Boolean is when the user cancels, so this approach doesn't need to know how to say False in the user's language.
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.
Im trying to figure out how to use vba code to select the no button in a messagebox. I have a workbook that opens and closes another workbook. When the workbook closes a message box pops up, i.e."Select yes or no". User normally manually will have to click no. Is there a way to do this with code?
This is the first workbook that opens the second workbook with the message box in it.
Option Explicit
Private Sub DONEBTN_Click()
Dim WRKBK2 As Workbook
Dim Name As String
Name = "Someones Name"
Set WRKBK2 = Workbooks.Open("C:\Second Workbook.xlsm")
WRKBK2.Sheets(1).Range("H7").Value = Name 'Name
WRKBK2.SaveAs Filename:="C:\New File Name For Workbook2.xlsm", _
FileFormat:=52, CreateBackup:=False, local:=True
Application.DisplayAlerts = False
WRKBK2.Close
Application.ScreenUpdating = True
End Sub
This is the code located in the second workbook that is under ThisWorkbook Private Sub Workbook_BeforeClose(Cancel As Boolean)
Option Explicit
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim MSG1 As String
MSG1 = MsgBox("Select yes or no?", vbYesNo, "Message Box")
If MSG1 = vbYes Then
' Code does something
Else
ThisWorkbook.Save
ThisWorkbook.Close
End If
End Sub
If you are referring to the "Save Workbook?" dialog box, use the SaveChanges option of the Workbook.Close method or Application.DisplayAlerts = False. Below example shows both.
Application.DisplayAlerts = False
Workbook("Sample Workbook.xlsx").Close SaveChanges:=False 'Or use .True to save the workbook before closing
Application.DisplayAlerts = True
If you are talking about the clipboard message, I addopted an stupid way out of it, but it works.
Range("A1").Select
Selection.Copy
I added this before close the file.
I have an excel file that all my colleagues must have read access, but only a few may have write access.
I tried to introduce in workbook_open a procedure to test user and depending on it to decide how the file to be opened. I learned that does not work directly, so I tried to access an add-in that has a procedure that changes the readonly status.
Private Sub Workbook_Open()
users = Environ("USERNAME")
Select Case users
Case "chris": MsgBox "ok"
Case "david": MsgBox "ok"
Case "sam": MsgBox "ok"
Case Else: Application.Run ("read_only")
End Select
End Sub
This is the sub function in the Addin
Sub read_only()
file_name = ActiveWorkbook.Path & "\" & ActiveWorkbook.Name
Status = ActiveWorkbook.readonly
ActiveWorkbook.Close ' (the problem is here because also this sub stops when my workbook closes)
If Status = False Then
Workbooks.Open fileName:=file_name, readonly:=True
Else
Workbooks.Open fileName:=file_name, readonly:=False
End If
End Sub
Has anyone an idea how to solve this?
You can do it directly :)
Try this
Private Sub Workbook_Open()
Users = Environ("USERNAME")
Select Case Users
Case "chris": MsgBox "ok"
Case "david": MsgBox "ok"
Case "sam": MsgBox "ok"
Case Else
Application.DisplayAlerts = False
On Error Resume Next
'may already be read only
If ThisWorkbook.Path <> vbNullString Then ThisWorkbook.ChangeFileAccess xlReadOnly
On Error GoTo 0
Application.DisplayAlerts = True
End Select
End Sub