I'm totally new to Microsoft VBA and I'm getting trouble to fix an Excel macro.
The intention of this macro is that, when pressing a button, it automatically saves the active worksheet on a file but it is not working and I don't know why.
It seems correct to me.
Sub Save()
'
' Save Macro
'
Sheets("My_sheet").Select
ChDir "C:\my_file"
ActiveWorkbook.SaveAs Filename:=Range("B6"), FileFormat:=xlOpenXMLWorkbookMacroEnabled, _
Password:="", WriteResPassword:="", ReadOnlyRecommended:=False, _
CreateBackup:=False
Sheets("My_sheet").Select
'
End Sub
it seems to work fine as long as the sheet name is set as "My_Sheet", folder exist and file name is correct.
You can try this to check if they are OK before saving:
Sub SaveMe()
Dim filename As String
'check if directory exist
If Dir("C:\my_file", vbDirectory) = "" Then
'if not ask if it should be created and continued
rspCreate = MsgBox("Directory doesn't exist, do you wish to create it and continue?", vbYesNo)
If rspCreate = vbYes Then
'create dir and carry on
MkDir "C:\my_file"
ElseIf rspCreate = vbNo Then
'no selected, stop execution
Exit Sub
End If
End If
filename = Range("B6")
Sheets("My_sheet").Select
ChDir "C:\my_file"
'check if file name is valid
If FileNameValid(filename) Then
ActiveWorkbook.SaveAs filename:=Range("B6"), FileFormat:=xlOpenXMLWorkbookMacroEnabled, _
Password:="", WriteResPassword:="", ReadOnlyRecommended:=False, _
CreateBackup:=False
Else
MsgBox "Invalid file name, file not saved"
End If
Sheets("My_sheet").Select
End Sub
'check if vali file name is used in cell
Function FileNameValid(sFileName As String) As Boolean
Dim notAllowed As Variant
Dim i As Long
Dim result As Boolean
'list of forbidden characters
notAllowed = Array("/", "\", ":", "*", "?", "< ", ">", "|", """")
'Initial result = OK
result = True
For i = LBound(notAllowed) To UBound(notAllowed)
If InStr(1, sFileName, notAllowed(i)) > 0 Then
'forbidden character used
result = False
Exit Function
End If
Next i
FileNameValid = result
End Function
Related
I have the code below. It makes me wonder why the BeforePrint event in the workbook codes is fired even though I am not printing anything. The workbook definitely is not blank. The error is in the creation of the PDF file.
The file does a simple job of saving the worksheet in a PDF format with the name of the sheet, the file path of the workbook, and some details inside the worksheet.
Anything that I am missing? I am not new to VBA but this bugs me a lot today. I am using MS Excel 2016 on Windows 7 ultimate.
Edit: I tried removing the following codes below but the problem still persists:
IgnorePrintAreas:=False, _
OpenAfterPublish:=True
The code is as follows:
Option Explicit
Public Sub createpdffile()
Dim wsA As Worksheet
Dim wbA As Workbook
Dim strPath As String
Dim strFile As String
Dim strPathFile As String
Dim myFile As Variant
Dim sheetname As String, sheetcode As String
Dim iRow As Long
Dim openPos As Integer
Dim closePos As Integer
'temporarily disable error handler so that I can see where the bug is.
'On Error GoTo errHandler
Set wbA = ActiveWorkbook
Set wsA = ActiveSheet
wbA.Save
'get last row of sheet and set print area to last row with L column
iRow = wsA.Cells(Rows.Count, 1).End(xlUp).Row
wsA.PageSetup.PrintArea = wsA.Range("A1:L" & iRow).Address
'just checking name in sheet and removing needed characters
sheetname = wsA.Name
openPos = InStr(sheetname, "(")
closePos = InStr(sheetname, ")")
sheetcode = Mid(sheetname, openPos + 1, closePos - openPos - 1)
'get active workbook folder, if saved
strPath = wbA.Path
If strPath = "" Then
strPath = Application.DefaultFilePath
End If
strPath = strPath & "\"
'create default name for saving file
strFile = sheetcode & " No. " & wsA.Cells(11, 9) & " - " & wsA.Cells(8, 3) & ".pdf"
strPathFile = strPath & strFile
'use can enter name and
' select folder for file
myFile = Application.GetSaveAsFilename _
(InitialFileName:=strPathFile, _
FileFilter:="PDF Files (*.pdf), *.pdf", _
Title:="Select Folder and FileName to save")
'export to PDF if a folder was selected
'THIS IS WHERE THE ERROR IS LOCATED
If myFile <> "False" Then
wsA.ExportAsFixedFormat _
Type:=xlTypePDF, _
Filename:=myFile, _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=True
'confirmation message with file info
MsgBox "PDF file has been created: " _
& vbCrLf _
& myFile
End If
exitHandler:
Exit Sub
errHandler:
MsgBox "Could not create PDF file" & vbNewLine & _
"Please complete the details needed!", vbOKOnly + vbExclamation, "Error Saving as PDF"
Resume exitHandler
End Sub
Solution from Foxfire and Burns and Burns' idea:
I added a public declaration before the main sub.
Option Explicit
'added line
Public myboolean as Boolean
Public Sub createpdffile()
myboolean = True
....
Then I added a line in the BeforePrint Event that says:
If myboolean = True Then Exit Sub
This now bypasses the BeforePrint event when the virtual PDF printer is called.
wsA.ExportAsFixedFormat
That line activates the BeforePrint Event. Actually, you are printing a PDF file. It works as a virtual PDF Printer.
sorry for the inconvenience. I've tried to google (I always said "google is my friend"), but everything I try only give me an error in VBA.
I would like to add a function, which replace invalid characters (!"#¤%&/()=?`^*>;:#£${[]}|~\,.'¨´+-) in filename with "_".
This is my current (and working) macro:
Sub Save_to_PDF()
Dim v As Variant
Dim name, datedd As String
ThisWorkbook.Sheets(Array("sheet1")).Select
datedd = Date
strFilename = Worksheets("sheet1").Range("B2")
v = Application.GetSaveAsFilename(strFilename & " document " & datedd & " .pdf", "PDF Files (*.pdf), *.pdf")
On Error GoTo openfile
If FileExists(v) Then
Kill v
End If
If VarType(v) = vbString Then
ThisWorkbook.Sheets("sheet1").Activate
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, filename:=v, _
Quality:=xlQualityStandard, IncludeDocProperties:=True, _
IgnorePrintAreas:=False, From:=1, To:=1, OpenAfterPublish:=True
End If
Exit Sub
openfile:
MsgBox "You have one file open allready whith that name. Please try again", vbInformation, "Please close file"
Exit Sub
End sub
The following Function will replace pre-selected characters with an alternative:
Function clean_filename(fname As String, replace_with As String)
Dim inv_chars As String
Dim cpos As Long
invchars = "!""#¤%&/()=?`^*>;:#£${[]}|~\,.'¨´+-"
For cpos = 1 To Len(invchars)
fname = Replace(fname, Mid(invchars, cpos, 1), replace_with)
Next
clean_filename = fname
End Function
You could use this by adding v = clean_filename(v,"_") once you've captured v (as a string).
However, you've included . and / in your invalid character list, and both are important to filenames so you may want to consider removing them and/or dealing with those in a different way.
I found some VBA code online and have made modifications for what I need. I've run into the one issue of being able to change the path. I was under the impression that:
CurrentFile = ThisWorkbook.FullName
Would call back the full file name including the path to where it is currently saved, but when I run the code it goes to my /Documents (not where the file are saved). Is there a way I can modify the below with a hardcoded path?
Sub SaveWorkbookAsNewFile()
Dim ActSheet As Worksheet
Dim ActBook As Workbook
Dim CurrentFile As String
Dim NewFileType As String
Dim NewFile As String
Dim NewFileName As String
NewFileName = "Checklist " & Format(Now, "MMMM-dd-yyyy")
Application.ScreenUpdating = False ' Prevents screen refreshing.
CurrentFile = ThisWorkbook.FullName
NewFileType = "Excel Files 1997-2003 (*.xls), *.xls," & _
"Excel Files 2007 (*.xlsx), *.xlsx," & _
"All files (*.*), *.*"
NewFile = Application.GetSaveAsFilename( _
InitialFileName:=NewFileName, _
fileFilter:=NewFileType)
If NewFile <> "" And NewFile <> "False" Then
ActiveWorkbook.SaveAs filename:=NewFile, _
FileFormat:=xlNormal, _
Password:="", _
WriteResPassword:="", _
ReadOnlyRecommended:=False, _
CreateBackup:=False
Set ActBook = ActiveWorkbook
Workbooks.Open CurrentFile
ActBook.Close
End If
Application.ScreenUpdating = True
End Sub code here
Just a minor tweak or 2 to your code will fix you. I commented your old code so you can see what I changed. You don't want to specify the file format when saving like you were doing as it will always prompt you about compatibility issues with changing the version if you are doing so. Leave it blank and it will just default to the version the sheet is already in. You can edit the C:\ after NewFile= to be whatever you need, just keep it in the quotes.
Alternately, you could change the default save location for excel, though that isn't a VBA fix.
Option Explicit
Sub SaveWorkbookAsNewFile()
Dim ActSheet As Worksheet
Dim ActBook As Workbook
Dim CurrentFile As String
Dim NewFileType As String
Dim NewFile As String
Dim NewFileName As String
NewFileName = "Checklist " & Format(Now, "MMMM-dd-yyyy")
Application.ScreenUpdating = False ' Prevents screen refreshing.
CurrentFile = ThisWorkbook.FullName
'NewFileType = "Excel Files 1997-2003 (*.xls), *.xls," & _
' "Excel Files 2007 (*.xlsx), *.xlsx," & _
' "All files (*.*), *.*"
NewFile = "C:\" & NewFileName
'NewFile = Application.GetSaveAsFilename( _
' InitialFileName:=NewFileName, _
' fileFilter:=NewFileType)
If NewFile <> "" And NewFile <> "False" Then
ActiveWorkbook.SaveAs Filename:=NewFile, _
Password:="", _
WriteResPassword:="", _
ReadOnlyRecommended:=False, _
CreateBackup:=False
' ActiveWorkbook.SaveAs Filename:=NewFile, _
' FileFormat:=xlNormal, _
' Password:="", _
' WriteResPassword:="", _
' ReadOnlyRecommended:=False, _
' CreateBackup:=False
Set ActBook = ActiveWorkbook
Workbooks.Open CurrentFile
ActBook.Close
End If
Application.ScreenUpdating = True
End Sub
If NewFile <> "" And NewFile <> "False" Then
actsheet.SaveAs ("C:/HardcodedLocationHere.xlsx") ' if this fails, actbook
FileFormat:=xlNormal, _
Password:="", _
WriteResPassword:="", _
ReadOnlyRecommended:=False, _
CreateBackup:=False
Set ActBook = ActiveWorkbook
Workbooks.Open CurrentFile
ActBook.Close
End If
when I run the code it goes to my /Documents (not where the file are saved)
This is because you've not provided a fully-qualified (full path) to the file, you've just given a Name, so it's opening the dialog with the default location of \Documents.
I prefer the FileDialog object instead of the Application.GetSaveAsFileName method.
Option Explicit
Sub SaveWorkbookAsNewFile()
Dim NewFile As String
Dim NewFileName As String
Dim fdlg as FileDialog
NewFileName = "Checklist " & Format(Now, "MMMM-dd-yyyy")
Application.ScreenUpdating = False ' Prevents screen refreshing.
Set fdlg = Application.FileDialog(msoFileDialogSaveAs)
fdlg.InitialFileName = ThisWorkbook.Path & Application.PathSeparator & NewFileName
fdlg.Show
If fdlg.SelectedItems.Count <> 1 Then GoTo EarlyExit
'# Gets the new file full path & name
NewFile = fdlg.SelectedItems(1)
ThisWorkbook.SaveCopyAs(NewFile)
EarlyExit:
Application.ScreenUpdating = True
End Sub
I have this code that creates a folder and a saves the actual file in it, but i want that it only saves a copy with only one sheet in it. So that the file with the code works like a template...
You write your stuff and press the button and it saves an .xlsx file with one sheet (the sheet with the form) in the new created folder... so you could do this with hundreds of files an folders.
So in the end it should work like this:
You open the .xlsm file where the code below is in.
You got to sheets one FORM (what should be "exported" later on) and
a list where you copy stuff in the form.
When you filled the form and press the button and it saves the Form
sheet in the new folder as .xlsx and you can continue in the .xlsm
file.
If it's unclear for you please ask.
The code i have now
Sub Macro1()
Dim strFilename, strDirname, strPathname, strDefpath As String
On Error Resume Next ' If directory exist goto next line
strDirname = Range("D81").Value ' New directory name
strFilename = Range("D8").Value 'New file name
strDefpath = Application.ActiveWorkbook.Path 'Default path name
If IsEmpty(strDirname) Then Exit Sub
If IsEmpty(strFilename) Then Exit Sub
MkDir strDefpath & "\" & strDirname
strPathname = strDefpath & "\" & strDirname & "\" & strFilename 'create total string
ActiveWorkbook.SaveAs Filename:=strPathname & ".xlsm", _
FileFormat:=xlOpenXMLWorkbookMacroEnabled, Password:="", WriteResPassword:="", _
ReadOnlyRecommended:=False, CreateBackup:=False
End Sub
Problem here is i have Names for the forms that are like 1102,1103 an going on like that. the next step is that there are files with the name 1102_1 and 1102_2 and they both should go in the folder 1102 ...
It's a bit out of my knownledge please help me guys :) greets
Now i am using this code below
Problem is that it always closes the xlsm file what really annoyes and when i reopen it it wants to update the file i need to remove that but i don't know how :/... and it only should export/save one special sheet
Private Sub CommandButton1_Click()
Dim strFilename As String, _
strDirname As String, _
strPathname As String, _
strDefpath As String, _
SheetToExport As String, _
WbMaster As Workbook, _
WbCopy As Workbook
On Error Resume Next ' If directory exist goto next line
strDirname = Range("W12").Value ' New directory name
strFilename = Range("D8").Value 'New file name
Set WbMaster = Application.ActiveWorkbook
SheetToExport = Range("A1").Value 'Or specify UserForm output
strDefpath = WbMaster.Path 'Default path name
If IsEmpty(strDirname) Then Exit Sub
If IsEmpty(strFilename) Then Exit Sub
MkDir strDefpath & "\" & strDirname
strPathname = strDefpath & "\" & strDirname & "\" & strFilename 'create total string
WbMaster.Sheets(SheetToExport).Copy
Set WbCopy = Application.ActiveWorkbook
WbCopy.SaveAs Filename:=strPathname & ".xlsx", _
FileFormat:=xlOpenXMLWorkbook, Password:="", WriteResPassword:="", _
ReadOnlyRecommended:=False, CreateBackup:=False
WbCopy.Close
End Sub
Be careful on your variable declaration!
The way you did it in your OP (original post) :
strFilename, strDirname and strPathname are declared as Variant and not as String.
You can still use them BUT it'll take much more memory and can be issue if you use them as arguments.
See the code :
Dim strFilename As String, _
strDirname As String, _
strPathname As String, _
strDefpath As String, _
SheetToExport As String, _
WbMaster As Workbook, _
WbCopy As Workbook
On Error Resume Next ' If directory exist goto next line
strDirname = Range("D81").Value ' New directory name
strFilename = Range("D8").Value 'New file name
Set WbMaster = Application.ActiveWorkbook
SheetToExport = Range("A1").Value 'Or specify UserForm output
strDefpath = WbMaster.Path 'Default path name
If IsEmpty(strDirname) Then Exit Sub
If IsEmpty(strFilename) Then Exit Sub
MkDir strDefpath & "\" & strDirname
strPathname = strDefpath & "\" & strDirname & "\" & strFilename 'create total string
WbMaster.Sheets(SheetToExport).Copy
Set WbCopy = Application.ActiveWorkbook
WbCopy.SaveAs Filename:=strPathname & ".xlsx", _
FileFormat:=xlOpenXMLWorkbook, Password:="", WriteResPassword:="", _
ReadOnlyRecommended:=False, CreateBackup:=False
ClosingWb = MsgBox("Do you wish to close the exported file?",vbYesNo,"Close exported file")
If ClosingWb <> vbNo Then WbCopy.Close
In the code below the file name is hard coded, but I want the user to be able to pick it.
I was reading about GetSaveAsFilename but I get an error when using it: "method or member not found".
fileSaveName = Application.GetSaveAsFilename _
(fileFilter:="Excel Files (*.txt), *.txt")
This is written for Word 2010. Am I wrong in thinking GetSaveAsFilename is available in word VBA?
Sub Macro3()
'
' Macro3 Macro
'
'
ActiveDocument.SaveAs2 FileName:="Questionnaire01-05-20122.txt", _
FileFormat:=wdFormatText, LockComments:=False, Password:="", _
AddToRecentFiles:=True, WritePassword:="", ReadOnlyRecommended:=False, _
EmbedTrueTypeFonts:=False, SaveNativePictureFormat:=False, SaveFormsData _
:=True, SaveAsAOCELetter:=False, Encoding:=1252, InsertLineBreaks:=False, _
AllowSubstitutions:=False, LineEnding:=wdCRLF, CompatibilityMode:=0
End Sub
I didn't realize that Word doesn't have GetSaveAsFileName or GetOpenFileName methods (which Excel has). But it doesn't. Instead you can try the SaveAs FileDialog (2003, 2007, 2010):
Sub ShowSaveAsDialog()
Dim dlgSaveAs As FileDialog
Set dlgSaveAs = Application.FileDialog(FileDialogType:=msoFileDialogSaveAs)
dlgSaveAs.Show
End Sub
You can provide a default path including filename like so to the dialog, ie
Sub SaveName()
Dim strFileName As String
Dim StrPath As String
'provide default filename
StrPath = "c:\temp\test.docx"
With Dialogs(wdDialogFileSaveAs)
.Name = StrPath
If .Display <> 0 Then
strFileName = .Name
Else
strFileName = "User Cancelled"
End If
End With
MsgBox strFileName
End Sub
Dim strFilePath, strFileName
strFilePath = "C:\Users\Public\Documents\"
strFileName = "put-filename-here.docx"
With Dialogs(wdDialogFileSaveAs)
.Name = strFilePath & strFileName
.Show
End With