Before anyone quickflags this: no, I did not forget to actually save the file after GetSaveAsFilename.
Basically, I've got a big VBA module that starts with an Excel file, processes a bunch of data, and generates a summary in Excel. I want it to be impossible to overwrite the file, and I need it to work in all cases (network drives, opening from email, etc). This is why I thought it would be best just to open a SaveAs box--leave the onus of the path on the user. However, when I trigger this method by saving with macros enabled, everything behaves as expected except the file itself does not save. The debugger says that fileName is what it should be at the time the SaveAs method is called, so I'm truly stumped here. There's no error thrown.
Thanks to anyone who can help! My code is below:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim fileName As String, oldName As String, fullName As String
Dim fragName() As String, noExtension As String, filePath As String
Dim newName As String
Cancel = True
oldName = ThisWorkbook.Name
fullName = ThisWorkbook.fullName
fragName() = Split(fullName, ".", 2)
noExtension = fragName(0)
filePath = ThisWorkbook.Path & "\"
Application.enableEvents = False
enterName:
fileName = Application.GetSaveAsFilename(InitialFileName:=filePath, _
FileFilter:="Microsoft Excel Worksheet (*.xlsx), *.xlsx")
On Error GoTo getOut
If fullName = fileName Then
MsgBox ("You have chosen the same name, " & oldName & vbCr _
& ", please choose something different.")
GoTo enterName
ElseIf fileName = "False" Then GoTo getOut
End If
ThisWorkbook.SaveAs (fileName)
getOut:
Application.enableEvents = True
End Sub
Thanks to Kyle's comment on my original question, I've figured out that the solution was to change
fileName = Application.GetSaveAsFilename(InitialFileName:=filePath, _
FileFilter:="Microsoft Excel Worksheet (*.xlsx), *.xlsx")
to:
fileName = Application.GetSaveAsFilename(InitialFileName:=filePath, _
FileFilter:="Microsoft Excel Macro-Enabled Worksheet (*.xlsm), *.xlsm")
Ideally I'd be able to get rid of the macros but this answers the question.
Related
I'm attempting to put together some code in VBA where it will open a specific folder, let me choose the file then continue running my code.
Currently what I have (below) "works" in that it will open a folder but usually it starts from a generic location (Desktop) but will not go the the specific folder location to let me open the file I want.
Dim Filename as String
filename = Application.GetOpenFilename(FileFilter:="Excel Files, *.xl*;*.xm*")
If filename <> False Then
Workbooks.Open filename:=filename
End If
I've also tried something like this:
Dim Directory as String
Dim Filename as String
Directory = "\\page\data\NFInventory\groups\CID\Retail Setting\Lago Retail Uploads\" & strBrand & "\" & strSeason & "\" & strPrefix & "\"
Filename = Dir(Directory & "*.xl*;*.xm*")
Workbooks.Open Filename:=Directory
But it doesn't do anything and I think I have everything right. Any help or push in the right direction would be greatly appreciated.
-Deke
This will start an Open Dialog at the specified location:
Sub openBeckJFolder()
With Application.FileDialog(msoFileDialogOpen)
.AllowMultiSelect = True
.Show
.InitialFileName = "C:\Users\beckj\"
End With
End Sub
The Microsoft document page doesn't really get into it, but FileDialog has several features such as the InitialFileName that I used here.
_
UPDATE: To open the workbook
Code added that allows you to highlight the workbook & click Open, or double-click on the workbook to open it.
Sub openBeckJFolder()
Dim Filename As String
With Application.FileDialog(msoFileDialogOpen)
.AllowMultiSelect = False
.InitialFileName = "C:\Users\beckj\"
If .Show = True Then
Filename = .SelectedItems(1)
End If
End With
Workbooks.Open (Filename)
End Sub
I recently received help here for an Excel spreadsheet we have that allows users to create quotations for customers. The spreadsheet uses VBA to allow the user to press a button which generates a PDF out from certain sheets, and attaches them to a new Outlook email.
Unfortunately this isn't working on one of the user's computers. The problem seems to be with the generating of the PDF. Initially when pressing the button, nothing happened. I suspected it was to do with the Microsoft Add-in to Save as PDF, so I made sure it was installed, which it was. After 'commenting out' the error message coming from the code to get to the real error message from Visual Basic, I found it to be this:
run-time error '-2147467261 (80004003)': Document not saved.
When clicking 'Debug' it highlights:
FileName = Create_PDF_Sheet_Level_Names(NamedRange:="addtopdf1", _
FixedFilePathName:=ThisWorkbook.Path & "\" & "Quotation - " & Range("G18") & ".pdf", _
OverwriteIfFileExist:=True, _
OpenPDFAfterPublish:=False)
Which relates to:
Function Create_PDF_Sheet_Level_Names(NamedRange As String, FixedFilePathName As String, _
OverwriteIfFileExist As Boolean, OpenPDFAfterPublish As Boolean) As String
'This function will create a PDF with every sheet with
'a sheet level name variable <NamedRange> in it
Dim FileFormatstr As String
Dim Fname As Variant
Dim Ash As Worksheet
Dim sh As Worksheet
Dim ShArr() As String
Dim s As Long
Dim SheetLevelName As Name
'Test If the Microsoft Add-in is installed
If Dir(Environ("commonprogramfiles") & "\Microsoft Shared\OFFICE" _
& Format(Val(Application.Version), "00") & "\EXP_PDF.DLL") <> "" Then
'We fill the Array with sheets with the sheet level name variable
For Each sh In ActiveWorkbook.Worksheets
If sh.Visible = -1 Then
Set SheetLevelName = Nothing
On Error Resume Next
Set SheetLevelName = sh.Names(NamedRange)
On Error GoTo 0
If Not SheetLevelName Is Nothing Then
s = s + 1
ReDim Preserve ShArr(1 To s)
ShArr(s) = sh.Name
End If
End If
Next sh
'We exit the function If there are no sheets with
'a sheet level name variable named <NamedRange>
If s = 0 Then Exit Function
If FixedFilePathName = "" Then
'Open the GetSaveAsFilename dialog to enter a file name for the pdf
FileFormatstr = "PDF Files (*.pdf), *.pdf"
Fname = Application.GetSaveAsFilename("", filefilter:=FileFormatstr, _
Title:="Create PDF")
'If you cancel this dialog Exit the function
If Fname = False Then Exit Function
Else
Fname = FixedFilePathName
End If
'If OverwriteIfFileExist = False we test if the PDF
'already exist in the folder and Exit the function if that is True
If OverwriteIfFileExist = False Then
If Dir(Fname) <> "" Then Exit Function
End If
Application.ScreenUpdating = False
Application.EnableEvents = False
'Remember the ActiveSheet
Set Ash = ActiveSheet
'Select the sheets with the sheet level name in it
Sheets(ShArr).Select
'Now the file name is correct we Publish to PDF
On Error Resume Next
ActiveSheet.ExportAsFixedFormat _
Type:=xlTypePDF, _
FileName:=Fname, _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=OpenPDFAfterPublish
On Error GoTo 0
'If Publish is Ok the function will return the file name
If Dir(Fname) <> "" Then
Create_PDF_Sheet_Level_Names = Fname
End If
Ash.Select
Application.ScreenUpdating = True
Application.EnableEvents = True
End If
End Function
I'm really scratching my head here! Checked all settings side-by-side with my machine on Excel and Outlook, including Trust Centre settings. Also checked add-ins.
Please check if there is enough disk space where the user wants to save the PDF file to!
I would recommend to check the length of the PDF fullname (path, filename and file extension; in your example it is the variable "Fname") as well before calling "ActiveSheet.ExportAsFixedFormat(...)", because filenames (or rather fullnames) under Microsoft Windows regularly cannot exceed more than 255 characters (see: Naming Files, Paths, and Namespaces).
The macro I made saves a template workbook as two separate files. One is saved per test (Location1,2,3, or 4) then is used in another macro to use the data from each test. The Second is a raw data file kept for back up. Now the issue is every time I run the test per location and run this macro it ask me if I want to save over the previous test. How can I tell it to say yes with out asking. Same for the do i want to save this workbook as a macro free workbook. What do i have to put in my code and where should i put it? Any helps is much appreciated.
Thanks
Solved Code:
Sub Auto_Open()
With Range("A30")
.Value = Time
.NumberFormat = "h-mm-ss AM/PM"
End With
Dim FileName As String
Dim FilePath As String
Dim FileDate As String
MyNote = "Is Cell 'B27' Overview Information" & SavePath & " Location1,2,3,or 4?"
Answer = MsgBox(MyNote, vbQuestion + vbYesNo)
If Answer = vbYes Then
FilePath = "C:\Users\aholiday\Desktop\FRF_Data_Macro_Insert_Test"
FileName = Sheets("Data").Range("B27").Text
Application.DisplayAlerts = False
ThisWorkbook.SaveAs FileName:=FilePath & "\" & FileName
Dim FileCopyName As String
Dim FileCopyPath As String
Dim FileTime As String
FilePath = "C:\Users\aholiday\Desktop\Backup"
FileName = Sheets("Data").Range("B27").Text
FileTime = Sheets("Data").Range("A30").Text
ThisWorkbook.SaveAs FileName:=FilePath & "\" & FileName & FileTime & ".xlsx", FileFormat:=xlOpenXMLWorkbook
MsgBox "File was saved!"
MsgBox "Ready for Next Test, Please Exit."
Application.DisplayAlerts = True
Else
MsgBox "File was not saved, Please Use Location_1,2,3or,4 Durring SIG ATM Test"
End If
End Sub
Add Application.DisplayAlerts = False before you try and save. Remember to turn in back to True after you've saved.
ConflictResolution should be xlLocalSessionChanges to not see the prompt
ConflictResolution:=Excel.XlSaveConflictResolution.xlLocalSessionChanges
from
How to use workbook.saveas with automatic Overwrite
Here is a snippet of the last part of a data manipulation macro:
Cells.EntireColumn.AutoFit
Application.ScreenUpdating = True
Dim fullfilenamelength As Integer, filenamelength As Integer
fullfilenamelength = Len(ThisWorkbook.FullName)
filenamelength = Len(udfWBFilename("ThisOne"))
Dim newFilePath As String, newFileFullName As String
newFilePath = Left(ThisWorkbook.FullName, fullfilenamelength - filenamelength)
newFileFullName = newFilePath & "Aspects List.xlsx"
ActiveWorkbook.SaveAs Filename:=newFileFullName, FileFormat _
:=xlOpenXMLWorkbook, CreateBackup:=False
Workbooks.Open Filename:=newFileFullName
Windows("Aspects List.xlsx").Activate
Beep
Application.DisplayAlerts = True
Application.StatusBar = False
End Sub
Here at the end, it saves the file as a macro-free workbook, then opens the new file.
Why does it close the old file when doing so?
(in other words, macro execution is stopped after running the line Windows("Aspects List.xlsx").Activate - the subsequent lines are never executed.)
Just remove this line
Workbooks.Open Filename:=newFileFullName
After performing ActiveWorkbook.SaveAs, your active workbook already refers to Aspects List.xlsx:
Before SaveAs:
After SaveAs:
Btw, it seems to me that
newFilePath = Left(ThisWorkbook.FullName, fullfilenamelength - filenamelength)
could be simplified to
newFilePath = ThisWorkbook.Path & "\"
Also it may be interesting: How to avoid using Select/Active statements
I have a savecopyas code at an at close prompt code that works, but if someone opens the copied document then trys to close it, the same copied VBA script within itself will try running the savecopyas to it's own path, resulting in an error/debug messagebox. My first idea would be to open the copied workbook in the background and delete all the VBA scripts then close and save as read only, however I also had a thought maybe I should just try to change the copied workbook to an .xlsx instead of it's original version .xslm format.
Any suggestions?
Here is what I have so far, but my question I guess is how do I open the copied workbook(not the original) and delete the VBA scripts in it in the background(not visible) then save and close?
Any help/suggestions would be much appreciated.
This is in my 'ThisWorkBook' module:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If Not Me.Saved Then
Msg = "Do you want to save the changes you made to "
Msg = Msg & Me.Name & "?"
Ans = MsgBox(Msg, vbQuestion + vbYesNoCancel)
Select Case Ans
Case vbYes
Me.Save
Case vbNo
Me.Saved = True
Case vbCancel
Cancel = True
Exit Sub
End Select
End If
Call Auto_Save 'Change this to your own subroutine
End Sub
This is in my 'Module1':
Option Explicit
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim backupfolder As String
backupfolder = "C:\Users\" & Environ("username") & "\Documents\John's Backup\"
ThisWorkbook.SaveCopyAs Filename:=backupfolder & ThisWorkbook.Name
End Sub
Sub Auto_Save()
Dim savedate
savedate = Date
Dim savetime
savetime = Time
Dim formattime As String
formattime = Format(savetime, "hh.MM.ss")
Dim formatdate As String
formatdate = Format(savedate, "DD - MM - YYYY")
Application.DisplayAlerts = False
Dim backupfolder As String
backupfolder = "C:\Users\" & Environ("username") & "\Documents\John's Backup\"
ActiveWorkbook.SaveCopyAs Filename:=backupfolder & ActiveWorkbook.Name
ActiveWorkbook.Save
Application.DisplayAlerts = True
MsgBox "Backup Run. Please Check at: " & backupfolder & " !"
End Sub
You nailed it - remove the macros by saving the workbook as an xlsx file (assuming you are using Excel 2007+).
If I understand your situation correctly, the workbook backup is saved when the workbook closes. So, I would save the workbook, then SaveAs the workbook, and then close the workbook.
One implementation could look like this:
ActiveWorkbook.Save
' Note that xlOpenXMLWorkbook = 41
ActiveWorkbook.SaveAs backupfolder & ActiveWorkbook.Name, FileFormat:= xlOpenXMLWorkbook
Separately, the folder location could fail if a user is on an older version of Windows (or if a future version has a different location for the Documents folder). So, instead of this:
backupfolder = "C:\Users\" & Environ("username") & "\Documents\John's Backup\"
do something like this:
Dim WshShell as Object
Set WshShell = CreateObject("WScript.Shell")
backupfolder = WshShell.SpecialFolders("MyDocuments") + "\John's Backup\"