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.
Related
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.
I have the following code:
Private Sub CommandButton3_Click()
Dim SPATH As String
Dim myFileName As Variant
If MsgBox("Some Question...", vbYesNo) = vbNo Then Exit Sub
'Used to open the VO2 report taken from the Metabolic Cart. Will close later
myFileName = Application.GetOpenFilename(FileFilter:="Excel Files,*.xls*")
If myFileName <> False Then
Application.ScreenUpdating = True
Workbooks.Open Filename:=myFileName
End If
MultiPage2.Value = 3
End Sub
It's job is to search for and open another Excel file while a userform is being run with the workbook it's currently tied to is visible=False with this:
Private Sub Workbook_Open()
Application.ScreenUpdating = False
ThisWorkbook.Application.Visible = False
UserForm2.Show
Windows(ThisWorkbook.Name).Visible = True
Application.Visible = True
Application.ScreenUpdating = True
End Sub
Also important note: Showmodal for this userform is True
When this is run using Excel 2016, it works no problem (i.e. I am able to use a refedit on the userform while the loaded Excel file is visible to use it on).
On my work computer which has an older version of Excel, the loaded Excel file is invisible (meaning I can't use the refedit I have on the userform).
Does anyone know what may be going on or have a possible solution?
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
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.
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