Hi probably a simple answer but im new to VBA.
I have a worksheet in a workbook. This worksheet has a specific reference in cell A1 which changes each time its used. It is basically an order number and formatted 03 01 15. The next will be 03 02 15, then 03 03 15 and so on.
What I want to do is to use VBA to save the sheet in a new workbook in my orders folder, and for the new workbook to be called the order number.
I can use the record macro function to get the basic VBA to copy the sheet, open a new workbook, paste the values and close the workbook, but im struggling with getting the name right. Each new workbook will have a different name based on the order number.
Any help would be appriciated.
Export a Worksheet to a Folder
Sub ExportWorksheetToFolder()
Const ProcTitle As String = "Export Worksheet to Folder"
' Define constants.
Const DESTINATION_SUBFOLDER_NAME As String = "Orders"
Const DESTINATION_FILE_NAME_ADDRESS As String = "A1"
' Reference the worksheet.
Dim ws As Worksheet: Set ws = ActiveSheet
' Instead, improve with e.g.
'Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Sheet1")
' Build the destination file path ('dFilePath').
' Since we will be saving an unsaved workbook (file), by not supplying
' the file extension and the parameter for the FileFormat argument
' of the SaveAs method, the new workbook will be saved
' with the .xlsx extension (losing any code in it) or,
' for Office prior to version 2007, with the .xls extension.
Dim pSep As String: pSep = Application.PathSeparator
' If the cell is blank, we don't have a name.
Dim dBaseName As String
dBaseName = CStr(ws.Range(DESTINATION_FILE_NAME_ADDRESS))
If Len(dBaseName) = 0 Then
MsgBox "Cell " & UCase(DESTINATION_FILE_NAME_ADDRESS) & " is blank.", _
vbCritical, ProcTitle
Exit Sub
End If
' If the workbook has never been saved, its path is "".
Dim wbPath As String: wbPath = ws.Parent.Path
If Len(wbPath) = 0 Then
MsgBox "You need to save the workbook to use this procedure.", _
vbCritical, ProcTitle
Exit Sub
End If
' Create the subfolder if it doesn't exist.
Dim dFolderPath As String: dFolderPath = wb.Path _
& pSep & DESTINATION_SUBFOLDER_NAME & pSep
If Len(Dir(dFolderPath, vbDirectory)) = 0 Then MkDir dFolderPath
Dim dFilePath As String: dFilePath = dFolderPath & dBaseName
' Copy.
ws.Copy ' copies the worksheet to a new workbook
' Save.
Dim MsgString As String
With Workbooks(Workbooks.Count) ' reference the new workbook
Application.DisplayAlerts = False
' 1. save without macros ... without confirmation
' 2. overwrite existing file ... without confirmation
On Error Resume Next
.SaveAs dFilePath
If Err.Number <> 0 Then ' invalid file name, file open...
MsgString = "Run-time error '" & Err.Number & "':" _
& vbLf & vbLf & Err.Description _
& vbLf & vbLf & "Could not save as '" & dFilePath & "'."
End If
On Error GoTo 0
Application.DisplayAlerts = True
.Close SaveChanges:=False
End With
' Inform.
If Len(MsgString) = 0 Then
MsgBox "Worksheet exported.", vbInformation, ProcTitle
Else
MsgBox MsgString, vbCritical, ProcTitle
End If
End Sub
Related
I'm stepping through the code to export a module using this post, but nothing happens. Is there a security setting to allow VBA permission to export a module?
I'm copying a few tabs from a workbook into a new workbook, but the tabs have macros which lead to broken links. To get around this I want to move the module and re-associate the macro. If I can't get this to work I will just copy the whole workbook and delete the info I don't want in the destination.
Here's the code from the above post:
Public Sub CopyModule(SourceWB As Workbook, strModuleName As String, TargetWB As Workbook)
' Description: copies a module from one workbook to another
' example: CopyModule Workbooks(ThisWorkbook), "Module2",
' Workbooks("Food Specials Rolling Depot Memo 46 - 01.xlsm")
' Notes: If Module to be copied already exists, it is removed first,
' and afterwards copied
Dim strFolder As String
Dim strTempFile As String
Dim FName As String
If Trim(strModuleName) = vbNullString Then
Exit Sub
End If
If TargetWB Is Nothing Then
MsgBox "Error: Target Workbook " & TargetWB.Name & " doesn't exist (or closed)", vbCritical
Exit Sub
End If
strFolder = SourceWB.Path
If Len(strFolder) = 0 Then strFolder = CurDir
' create temp file and copy "Module2" into it
strFolder = strFolder & "\"
strTempFile = strFolder & "~tmpexport.bas"
On Error Resume Next
FName = Environ("Temp") & "\" & strModuleName & ".bas"
If Dir(FName, vbNormal + vbHidden + vbSystem) <> vbNullString Then
Err.Clear
Kill FName
If Err.Number <> 0 Then
MsgBox "Error copying module " & strModuleName & " from Workbook " & SourceWB.Name & " to Workbook " & TargetWB.Name, vbInformation
Exit Sub
End If
End If
' remove "Module2" if already exits in destination workbook
With TargetWB.VBProject.VBComponents
.Remove .Item(strModuleName)
End With
' copy "Module2" from temp file to destination workbook
SourceWB.VBProject.VBComponents(strModuleName).Export strTempFile
TargetWB.VBProject.VBComponents.Import strTempFile
Kill strTempFile
On Error GoTo 0
End Sub
I have a macro to see if a cell contains this string if so executes a "save as" command with this set name standard. When I try to run the macro the if statements seem to not work. When I go through step by step it hits the if statements but saves the personal.xlsb instead of the file I'm working on. Here the code I know I have something wrong with it
Dim FName As String
Dim FPath As String
Dim answer As Integer
If ActiveWorkbook.Sheets("Sheet1").Range("A1") = "String1" Then
FPath = "C:\String1"
FName = Sheets("Sheet1").Range("A1").Text
If Len(FPath & "\" & FName) = 0 Then
answer = MsgBox("Do you want to Save File As: " & FName & "?", vbYesNo + vbQuestion, "Microsoft Excel")
If answer = vbYes Then
ThisWorkbook.SaveAs Filename:=FPath & "\" & FName
End If
Else
ThisWorkbook.Save
End If
End If
I am open to suggestion the most I was is to check if the file contains a string if so verify it does not already exist and if so just save instead of save as.
ThisWorkbook refers to the workbook where the code resides. Presumably, the code being in the Personal.xlsb, that is why it's saving the XLSB file and not the activeworkbook.
Try this instead:
Dim FName As String
Dim FPath As String
Dim fullName As String
Dim rng As Range
Dim s as String
s = "String1"
With ActiveWorkbook
Set rng = .Sheets("Sheet1").Range("A1")
If rng.Value = s Then
FPath = "C:\" & s
FName = rng.Text
fullName = FPath & "\" & FName
If Len(fullName) = 0 Then
If MsgBox("Do you want to Save File As: " & FName & "?", vbYesNo + vbQuestion, "Microsoft Excel") = vbYes Then
.SaveAs Filename:=fullName
End If
Else
.Save
End If
End If
End With
I have a 120+ sheet workbook, the front page of which has a nice function to extract a specified sheet, saving it as a new book with a bunch of details. Which all works fine. Trying to add a new function though. On the extracted sheet, I've added a button and created a macro that will e-mail the finished article. The problem is, the location reference for the macro keeps defaulting back to the original book source, rather than the sheet itself (its all .XLSM files). The macro itself is on each sheet, but I can't find a way of fixing the reference for the macro to the sheet proper. And my google-fu has failed me. Any input or words of wisdom would be greatly appreciated!
OK, here's the mailer macro:
Sub Mail_FinishedSheet_Array()
Dim wb1 As Workbook
Dim wb2 As Workbook
Dim TempFilePath As String
Dim TempFileName As String
Dim FileExtStr As String
Dim OutApp As Object
Dim OutMail As Object
Dim SigString As String
Dim Signature As String
Dim StrBody As String
Set wb1 = ActiveWorkbook
If Val(Application.Version) >= 12 Then
If wb1.FileFormat = 51 And wb1.HasVBProject = True Then
MsgBox "There is VBA code in this xlsx file. There will" & vbNewLine & _
"be no VBA code in the file you send. Save the" & vbNewLine & _
"file as a macro-enabled (. Xlsm) and then retry the macro.", vbInformation
Exit Sub
End If
End If
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Signature details with path
SigString = Environ("appdata") & _
"\Microsoft\Signatures\Zonal2014HO.htm"
If Dir(SigString) <> "" Then
Signature = GetBoiler(SigString)
Else
Signature = ""
End If
' Make a copy of the file.
' If you want to change the file name then change only TempFileName variable.
TempFilePath = Environ$("temp") & "\"
TempFileName = wb1.Name & " " & Format(Now, "dd-mmm-yy hh-mm")
FileExtStr = "." & LCase(Right(wb1.Name, _
Len(wb1.Name) - InStrRev(wb1.Name, ".", , 1)))
wb1.SaveCopyAs TempFilePath & TempFileName & FileExtStr
Set wb2 = Workbooks.Open(TempFilePath & TempFileName & FileExtStr)
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
'Body contents for HTML format e-mail
StrBody = "<BODY style=font-size:11pt;font-family:Calibri>Hi," _
& "<p>Please find a completed checksheet attached for a PC Rebuild." _
& "<p>Regards, " _
& "<p></BODY>"
' Change the mail address and subject in the macro before you run this procedure.
With OutMail
.To = "Eng_Tech_support#zonal.co.uk"
.CC = "rob.brown#zonal.co.uk"
.BCC = ""
.Subject = "Completed PC Rebuild Checksheet " & Format(Now, "dd-mmm-yy")
.HTMLbody = StrBody & Signature
.Attachments.Add wb2.FullName
' You can add other files by uncommenting the following line.
'.Attachments.Add ("C:\test.txt")
' In place of the following statement, you can use ".Display" to
' display the mail.
.Display
End With
On Error GoTo 0
wb2.Close SaveChanges:=False
' Delete the file.
' Kill TempFilePath & TempFileName & FileExtStr
Set OutMail = Nothing
Set OutApp = Nothing
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
And here's the extraction macro from the main page that seperates the desires sheet from the book and saves it as a new file:
Sub Full_Extract()
Dim wbkOriginal As Workbook
Set wbkOriginal = ActiveWorkbook
'sets site and engineer details into the estate page that is being extracted
Worksheets(Sheet1.CmbSheet.Value).Range("B3").Value = Worksheets("front page").Range("E6")
Worksheets(Sheet1.CmbSheet.Value).Range("D3").Value = Worksheets("front page").Range("N6")
Worksheets(Sheet1.CmbSheet.Value).Range("F3").Value = Worksheets("front page").Range("K6")
Worksheets(Sheet1.CmbSheet.Value).Range("B4").Value = Worksheets("front page").Range("F8")
Worksheets(Sheet1.CmbSheet.Value).Range("D4").Value = Worksheets("front page").Range("K8")
' copies sheet name from combo box into new document, saves it with site name and current date
' into C:\Temp\ folder for ease of access
With ActiveWorkbook.Sheets(Array((Sheet1.CmbSheet.Value), "Z-MISC"))
.Copy
ActiveWorkbook.SaveAs _
"C:\temp\" _
& ActiveWorkbook.Sheets(Sheet1.CmbSheet.Value).Cells(3, 2).Text _
& " " _
& Format(Now(), "DD-MM-YY") _
& ".xlsm", _
xlOpenXMLWorkbookMacroEnabled, , , , False
End With
'code to close the original workbook to prevent accidental changes etc
Application.DisplayAlerts = False
wbkOriginal.Close
Application.DisplayAlerts = True
End Sub
use an ActiveX button
which requires its associated code to be in the worksheet it resides in and that after that .Copy and ActiveWorkbook.SaveAs ... statements will point to the worksheet in newly created workbook
Mail_FinishedSheet_Array() Sub must also be in the new workbook if you want to make it independent from "Checkbook.xlsm". In this case that Sub must reside in one of the two worksheets (Sheet1.CmbSheet.Value or "Z-MISC") being copied in the new workbook
user3598756 nailed it. Using an ActiveX button and then assigning the macro to it directly (right click, view code) has worked perfectly.
I am having problems with my code since it only works in the specific folders but not in all subfolders inside the particular folder.
Could someone please helps to make the code works to all subfolders inside that specific folder? :)
These are my code:
Sub Execute1()
Dim monthstr As String
Dim year As String
Dim monthtext As String
Dim prevmonth As String
Dim prevmonthtext As String
year = Range("D8").Text
monthstr = Trim(Range("D9").Text)
monthtext = Trim(Range("D10").Text)
prevmonth = Trim(Range("D11").Text)
prevmonthtext = Trim(Range("D12").Text)
prevyear = Trim(Range("D13").Text)
'confirmation box before running macro//////////////////////////////////////////////////////////////////////////////////////
response = MsgBox("Are you sure the settings are correct?", vbYesNo, "Confirmation")
If response = vbNo Then
Exit Sub
End If
'optimize macro speed///////////////////////////////////////////////////////////////////////////////////////////////////////////
Call Optimize
'finding the correct path (month)//////////////////////////////////////////////////////////////////////////////////////////
Dim myfile As String
Dim mypath As String
Dim newpath As String
mypath = "C:\Users\praseirw\Desktop\Tes CC\" & prevyear & "\SC\" & prevmonth & " " & prevmonthtext & "\"
myfile = Dir(mypath & "*.xlsx")
newpath = "C:\Users\praseirw\Desktop\Tes CC\" & year & "\SC\" & monthstr & " " & monthtext & "\"
'loop through all files in specified month//////////////////////////////////////////////////////////////////////////////////
Dim root As Workbook
Dim rng As Range
Dim wb As Workbook
Dim ws As Worksheet
Set root = Workbooks("CC Reports Center.xlsm")
Set rng = root.Worksheets("Settings").Range("H7:H14")
Do While myfile <> ""
Set wb = Workbooks.Open(mypath & myfile)
For Each ws In wb.Worksheets
rng.Copy
With ws.Range("D1")
.PasteSpecial xlPasteFormulas
End With
Next ws
Dim oldname As String
Dim newname As String
Dim wbname As String
oldname = wb.Name
wbname = Mid(oldname, 9)
newname = year & "_" & monthstr & "_" & wbname
wb.SaveAs Filename:=newpath & newname
wb.Close
Set wb = Nothing
myfile = Dir
Loop
Application.CutCopyMode = False
MsgBox "Task Complete!"
'reset macro optimization settings//////////////////////////////////////////////////////////////////////////////////////////////
Call ResetOptimize
End Sub
Here's one way to do it with the Dir function. If you want something a little more elegant you may want to consider using a FileSystemObject. (Note that to view Debug.Print output you have to enable the immediate window from under view.)
Sub test()
Dim root As String
root = "C:\"
Dim DC As New Collection
s = Dir(root & "*", vbDirectory)
Do Until s = ""
DC.Add s
s = Dir
Loop
For Each D In DC
Debug.Print D
On Error Resume Next: s = Dir(root & D & "\*.xl*"): On Error GoTo 0
Do Until s = ""
Debug.Print " " & s
s = Dir
Loop
Next
End Sub
Here's an example of how to do this with a FileSystemObject. Note that my code is a little sloppy with "On error resume next" to protect against access denied or other errors. Realistically you may want to consider incorporating better error handling, but that's another topic. Using a FileSystemObject is more powerful than Dir because Dir only returns a string, while FileSystemObject lets you work with files and folders as actual objects, which are much more powerful.
Sub test()
'You can use "CreateObject..." to add a FileSystemObject from the Scipting Library
'Alternatively, you can add a reference to "Microsoft Scripting Runtime"
'allowing you to directly declare a filesystemobject and access related intellisense
Set fso = CreateObject("Scripting.FileSystemObject")
Set Folder = fso.GetFolder("C:\")
For Each SubFolder In Folder.SubFolders
Debug.Print SubFolder.Name
On Error Resume Next
For Each File In SubFolder.Files
Debug.Print " " & File.Name
Next
On Error GoTo 0
Next
End Sub
My workbook has 5 different sheets and I need to copy the five sheets and paste it into 5 different mails. Preferably as HTML.
The below written code only attaches the different sheets to outlook. I need the HTML below the body of the email. Please note that my range in the sheets varies from workbook to workbook but the sheet names remain the same.
Function BrowseForFolder(Optional OpenAt As Variant) As Variant
'Function purpose: To Browser for a user selected folder.
'If the "OpenAt" path is provided, open the browser at that directory
'NOTE: If invalid, it will open at the Desktop level
'BrowseForFolder was a code originally written by Ron De Bruin, I love this function!
Dim ShellApp As Object
'Create a file browser window at the default folder
Set ShellApp = CreateObject("Shell.Application"). _
BrowseForFolder(0, "Please choose a folder", 0, OpenAt)
'Set the folder to that selected. (On error in case cancelled)
On Error Resume Next
BrowseForFolder = ShellApp.self.Path
On Error GoTo 0
'Destroy the Shell Application
Set ShellApp = Nothing
'Check for invalid or non-entries and send to the Invalid error
'handler if found
'Valid selections can begin L: (where L is a letter) or
'\\ (as in \\servername\sharename. All others are invalid
Select Case Mid(BrowseForFolder, 2, 1)
Case Is = ":"
If Left(BrowseForFolder, 1) = ":" Then GoTo Invalid
Case Is = "\"
If Not Left(BrowseForFolder, 1) = "\" Then GoTo Invalid
Case Else
GoTo Invalid
End Select
Exit Function
Invalid:
'If it was determined that the selection was invalid, set to False
BrowseForFolder = False
End Function
Sub SaveWorksheets()
'saves each worksheet as a separate file in a specific folder.
Dim ThisFolder As String
Dim NameOfFile As String
Dim Period As String
Dim RecipName As String
ThisFolder = BrowseForFolder()
Application.ScreenUpdating = False
Dim ws As Worksheet
Dim wsName As String
For Each ws In ActiveWorkbook.Worksheets
wsName = ws.Name
If wsName <> "Data" Then
Period = ws.Cells(4, 1).Value 'put the row and column numbers of the report date here.
RecipName = ws.Cells(1, 29).Value 'put the row and column numbers of the email address here
NameOfFile = ThisFolder & "\" & "Termination Report " & wsName & " " & Period & ".xlsx"
ws.Select
ws.Copy
ActiveWorkbook.SaveAs Filename:= _
NameOfFile, FileFormat:= _
xlOpenXMLWorkbook, CreateBackup:=False
ActiveWindow.Close
Call EmailWorkbooks(RecipName, NameOfFile)
End If
Next ws
End Sub
Sub EmailWorkbooks(RecipName, NameOfFile)
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.createItem(0)
Msg = "Attached is the xyz report for your review. Please let me know if you have any questions" & vbCrLf & vbCrLf _
& "Thanks," & vbCrLf & vbCrLf _
& "Your Name Here" & vbCrLf _
& "Your Title" & vbCrLf _
& "Your contact info"
Subj = "XYZ Report" & " " & Period
On Error Resume Next
With OutMail
.To = RecipName
'.CC =
.Subject = Subj
.Body = Msg
.Attachments.Add (NameOfFile)
.Save
End With
On Error GoTo 0
End Sub
U can use Add method of PublishObjects collection, short example:
Sub InsertSheetContent()
Dim onePublishObject As PublishObject
Dim oneSheet As Worksheet
Dim scriptingObject As Object
Dim outlookApplication As Object
Dim outlookMail As Object
Dim htmlBody As String
Dim htmlFile As String
Dim textStream
Set scriptingObject = CreateObject("Scripting.FileSystemObject")
Set outlookApplication = CreateObject("Outlook.Application")
For Each oneSheet In ThisWorkbook.Worksheets
htmlFile = ThisWorkbook.Path & "\" & ThisWorkbook.Name & "_" & oneSheet.Name & ".html"
Set onePublishObject = ThisWorkbook.PublishObjects.Add(SourceType:=xlSourceRange, _
Filename:=htmlFile, _
Sheet:=oneSheet.Name, _
Source:=oneSheet.UsedRange.Address, _
HtmlType:=xlHtmlStatic, _
DivID:=oneSheet.Name)
onePublishObject.Publish Create:=True
Set textStream = scriptingObject.OpenTextFile(htmlFile)
htmlBody = textStream.ReadAll
Set outlookMail = outlookApplication.CreateItem(0)
With outlookMail
.htmlBody = htmlBody
.Display
End With
Next oneSheet
End Sub