Excel VBA force save as .xlsm - excel

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

Related

Excel VBA, ActiveWorkbook.Save trigger the event Workbook_BeforeSave, but the code line in Workbook_BeforeSave is passed without any result

I've searched this site and found similar problem but still different.
Those I found in this site (such as this, this and this) involve too much code (which maybe the reason it doesn't do correctly) and also involve Workbook_BeforeClose event.
Mine is very simple as follow :
Sub RefreshData()
ActiveWorkbook.Save
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Application.DisplayAlerts = False
MsgBox "test"
Range("A1").Select
Range("A3").Value = "test"
Sheets(Array("TABEL", "DATA")).Copy
ActiveWorkbook.SaveAs Filename:=ThisWorkbook.Path + "\Backup\blablabla " & Format(Now(), "yymmdd hh mm ss") & ".xlsx", FileFormat:=51
ActiveWorkbook.Close
Application.DisplayAlerts = True
End Sub
When I run the RefreshData sub, it trigger to Workbook_BeforeSave sub.
Within the code in Workbook_BeforeSave, when the yellow line pass the msgbox code it show the result as Excel shows the message box. But when the yellow line pass the rest of the code, it does nothing, no error. Range("A1") not selected but it does have the "test" value. New workbook with sheets DATA and TABEL not created, letalone is saved to the backup folder and close it. Yet, the workbook with the macro is saved.
My question : is that normal ?
My hope : someone will be kind enough to replicate the code above in a new workbook in his Excel app and run it. If all the codes in Workbook_BeforeSave work accordingly, then there's something wrong with my Excel app and I hope someone can inform me what might be the cause within my Excel app.
Any kind of help would be greatly appreciated.
Thank you in advanced.
More a suggestion than an answer, but:
Try properly qualifying ranges:
change Range("A1").Value = test
into ThisWorkbook.Range("A1").Value = test
Also if it's about ThisWorkbook, use that instead of ActiveWorkbook.

How to disable SaveAs in an open workbook but NOT disable Save

I am unable to find any code that ONLY disables SaveAs functionality without disabling Save.
The code listed is very effective in disabling SAVE and SAVE AS, but I want users to be able to save data but NOT have the opportunity to SAVEAS so they cannot create version of the work book. (copying a file in file manager is not a problem in this case - just saveas is the problem.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim xName As String
xName = "CancelBeforeSave"
If Not Evaluate("=ISREF('" & xName & "'!A1)") Then
Sheets.Add(after:=Worksheets(Worksheets.Count)).Name = xName & ""
Sheets(xName & "").Move after:=Worksheets(Worksheets.Count)
'To edit macros disable by changing to True
'Need to open workbook first with macros disabled
Sheets(xName & "").Visible = False
Exit Sub
End If
'To edit macros disable by changing to False
'Need to open workbook first with macros disabled
Cancel = True
End Sub
I would expect the workbook when open to not allow saveas without affecting other open workbooks.
Alternately from the code I supplied if we can just re-enable the save funtionality would be acceptable as well.
Just test if SaveAsUI is true and cancel saving.
Option Explicit
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If SaveAsUI Then
MsgBox "Save As is disabled", vbInformation
Cancel = True
End If
End Sub
In the documentation of the Workbook.BeforeSave event you can find:
SaveAsUI
True if the Save As dialog box will be displayed due to changes made that need to be saved in the workbook.
Note that this is not a security feature.
This prevents users from using the dialog box "Save As". But with some VBA code in any other Excel sheet you can easily trick this. Anything you do to try to disallow a real save as can be worked around. This will not be a security feature. It's just to prevent save as "by accident". Anyone who really wants to do a save as and knows how to trick it will still be able to do it.

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.

Excel to tsv automatic updation

Is there any scrips or tooling that could convert all the excel changes / editions dynamically into the tsv file ? My requirement is to make the changes done in the excel sheet to get reflected on to the tsv file of the same dynamically, the moment we save the excel sheet, its tsv should be edited and should contained the modification.
Thanks in advance guys!!
This VBA macro is based on work over at Mr. Excel but extended to save in two formats at once.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
' break the save
Cancel = True
' perform the save wourself
Application.EnableEvents = False
Me.SaveAs Filename:="c:\tmp\x.xlsm", _
FileFormat:=xlOpenXMLWorkbookMacroEnabled, CreateBackup:=False
Application.EnableEvents = True
' do something after the save
Me.SaveAs Filename:="c:\tmp\x.tsv", _
FileFormat:=xlCurrentPlatformText, CreateBackup:=False
MsgBox "Workbook is saved in xlsm and tsv"
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