copy worksheet, code and button to a new file - excel

I have created some codes and one of my requirement is to copy certain sheets, modules and buttons to refer those modules to a new workbook.
I am facing two problems:
1) While trying various things I am able to copy worksheets and module. However, the problem is when I copy module buttons to new worksheet, it still refers to the original file and not the new file which has been created.
2) When the button delete command runs it deletes buttons from existing workbook and inserts a new button in existing workbook.
I can understand that somewhere I am not getting back to original file but not able to make out where and how to go to new file to execute the code.
The code for copying file, modules and buttons is as listed below.
Sub Workbook_Open()
Dim filename4 As String:
strFilename4 = "\Work Data " & Format(Now(), "ddmmyy hhmmss")
filename4 = ActiveWorkbook.Path & strFilename4 & ".xlsm"
Dim nm As Name
Dim ws As Worksheet
Sheets(Array("Sheet1", "Sheet2")).Copy
For Each nm In ActiveWorkbook.Names
If InStr(1, nm.RefersTo, "#REF!") > 0 Then
Debug.Print nm.Name & ": deleted"
nm.Delete
End If
Next nm
ActiveWorkbook.SaveAs filename:=filename4, FileFormat:=xlOpenXMLWorkbookMacroEnabled, Password:="", WriteResPassword:="", ReadOnlyRecommended:=False _
, CreateBackup:=False
ActiveWorkbook.Close
Const MODULE_NAME As String = "DataValidityCheck" ' Name of the module to transfer
Const TEMPFILE As String = "c:\DataValidityCheck.bas" ' temp textfile
Dim WBK As Workbook
Set WBK = Workbooks.Open(filename4)
'Copy Module to New Workbook
On Error Resume Next
Set WBK = Workbooks(filename4)
ThisWorkbook.VBProject.VBComponents(MODULE_NAME).Export TEMPFILE
WBK.VBProject.VBComponents.Import TEMPFILE
Kill TEMPFILE
'Delete every shape in the Shapes collection
Dim myshape As Shape
For Each myshape In ActiveSheet.Shapes
myshape.Delete
Next myshape
ThisWorkbook.ActiveSheet.Buttons.Add(2538, 4.5, 71.25, 14.25).Select
With btn
.Caption = "Validate Data" 'change the name of the button accordingly
.OnAction = "msg"
End With
Selection.OnAction = "Workbook_Open"
ActiveWorkbook.Close SaveChanges:=True
End If
Application.CutCopyMode = False
End Sub

Your problem stems from the fact that you are not qualifying your workbooks correctly. Using ThisWorkbook will always signify the workbook running the code. Using ActiveWorkbook will always signify the workbook that is active at that moment in the codes execution. While there are perfectly legitimate times and places to use this, its generally a bad practice to do so, especially ActiveWorkbook (and ActiveSheet for that matter).
I have refactored your code with full comments to illustrate this, as well as cleaned up some other syntax related stuff that was in there.
Sub Workbook_Open()
Const MODULE_NAME As String = "DataValidityCheck" ' Name of the module to transfer
Const TEMPFILE As String = "c:\DataValidityCheck.bas" ' temp textfile
'qualify main workbook
Dim wbkMain As Workbook
Set wbkMain = ThisWorkbook
'export desired module
With wbkMain
.VBProject.VBComponents(MODULE_NAME).Export TEMPFILE
'copy out sheets
.Sheets(Array("Sheet1", "Sheet2")).Copy
End With
'qualify new workbook
Dim WBK As Workbook
Set WBK = ActiveWorkbook 'this is one of only a few times its required to use 'ActiveWorkbook'
'work directly with new workbook
With WBK
'Copy Module to New Workbook
.VBProject.VBComponents.Import TEMPFILE
Kill TEMPFILE
'delete bad names
Dim nm As Name
For Each nm In .Names
If InStr(1, nm.RefersTo, "#REF!") Then nm.Delete
Next
'Delete every shape in the Shapes collection
With .Sheets(1) 'change to 2 if you need sheet 2
Dim myshape As Shape
For Each myshape In .Shapes 'change to 2 if you need sheet 2
myshape.Delete
Next myshape
.Buttons.Add(2538, 4.5, 71.25, 14.25).Select
With Selection 'should really set this to a variable as well, but I didn't feel like looking the right syntax
.Caption = "Validate Data" 'change the name of the button accordingly
.OnAction = "msg" 'Workbook_Open if need be
End With
End With
'finally save the new workbook
Dim filename4 As String, strFilename4 As String
strFilename4 = "\Work Data " & Format(Now(), "ddmmyy hhmmss")
filename4 = ActiveWorkbook.Path & strFilename4 & ".xlsm"
.SaveAs Filename:=filename4, FileFormat:=xlOpenXMLWorkbookMacroEnabled, Password:="", WriteResPassword:="", ReadOnlyRecommended:=False _
, CreateBackup:=False
.Close True 'don't need since you just saved, but why not
End With
Application.CutCopyMode = False
End Sub

Related

copy more than one sheets using VBA macro

i'm a beginner in VBA and i need to do the following. Starting from a workbook i should create another one without formulas and macro code.
I found some solutions and based on that i modeled my own code:
Sub SaveValuesOnly()
Dim wsCopy As Worksheet, wsPaste As Worksheet
Dim wb As Workbook
Dim sFileName As String, sPath As String
sPath = "C:\Users\"
sFileName = "OVERALL RECAP"
Set wsCopy = ThisWorkbook.Worksheets("INCIDENTS")
Set wb = Workbooks.Add
Set wsPaste = wb.Sheets(1)
wsCopy.Cells.copy
wsPaste.Cells.PasteSpecial xlPasteValues
wsPaste.Cells.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
wsPaste.Name = "Expenses" 'Change if needed
wb.SaveAs Filename:=sPath & sFileName, FileFormat:=xlOpenXMLWorkbook
End Sub
I need to copy more than one sheet and tried to use the official documentation like:
Worksheets(Array("Sheet1", "Sheet2", "Sheet4")).Copy
With ActiveWorkbook
.SaveAs Filename:=Environ("TEMP") & "\New3.xlsx", FileFormat:=xlOpenXMLWorkbook
.Close SaveChanges:=False
End With
But i didn't manage to implement this into the code above, any suggestion? Thanks.
Copy Worksheets to New Workbook
The Flow
Basically, the procedure will:
create a copy of ThisWorkbook (the workbook containing this code) in the destination folder,
open the copy and continue to work with it,
copy values to (remove formulas from) the specified worksheets,
delete the not specified sheets,
rename the specified worksheets,
save the copy to a new workbook in .xlsx format,
delete the copy.
Remarks
If a workbook with the same name (e.g. OVERALL RECAP) is already open, it will crash Excel.
Be careful when determining the worksheet names, because if you try to rename a worksheet using an already existing name, an error will occur.
The Code
Option Explicit
Sub copyWorksheets()
Const dPath As String = "C:\Users"
Const dFileName As String = "OVERALL RECAP"
Const CopyList As String = "INCIDENTS,Sheet2,Sheet3"
Const PasteList As String = "Expenses,Sheet2,Sheet4"
Dim wb As Workbook: Set wb = ThisWorkbook
Dim CopyNames() As String: CopyNames = Split(CopyList, ",")
Dim PasteNames() As String: PasteNames = Split(PasteList, ",")
Dim nUpper As Long: nUpper = UBound(CopyNames)
Dim tFilePath As String: tFilePath = dPath & "\" & "t_" & wb.Name
Application.ScreenUpdating = False
' Save a copy.
wb.SaveCopyAs tFilePath
' Work with the copy.
With Workbooks.Open(tFilePath)
' Copy values (remove formulas).
Dim n As Long
For n = 0 To nUpper
With .Worksheets(CopyNames(n)).UsedRange
.Value = .Value
End With
Next n
' Delete other sheets.
Dim dCount As Long: dCount = .Sheets.Count - nUpper - 1
If dCount > 0 Then
Dim DeleteNames() As String: ReDim DeleteNames(1 To dCount)
Dim sh As Object ' There maybe e.g. charts.
n = 0
For Each sh In .Sheets
If IsError(Application.Match(sh.Name, CopyNames, 0)) Then
n = n + 1
DeleteNames(n) = sh.Name
End If
Next sh
Application.DisplayAlerts = False
.Sheets(DeleteNames).Delete
Application.DisplayAlerts = True
End If
' Rename worksheets.
For n = 0 To nUpper
If CopyNames(n) <> PasteNames(n) Then
.Worksheets(CopyNames(n)).Name = PasteNames(n)
End If
Next n
' Save workbook.
.Worksheets(1).Activate
Application.DisplayAlerts = False
.SaveAs _
Filename:=dPath & "\" & dFileName, _
FileFormat:=xlOpenXMLWorkbook
Application.DisplayAlerts = True
'.Close SaveChanges:=False ' Close the new workbook.
End With
' Delete the copy.
Kill tFilePath
Application.ScreenUpdating = True
MsgBox "Workbook created.", vbInformation, "Success"
'wb.Close SaveChanges:=False ' Close ThisWorkbook.
End Sub
The code below takes the opposite approach to the earlier one. It copies the entire workbook to a new name and then modifies it. You can list the sheets you want to keep. Formulas in them will be converted to their values. Sheets not listed will be deleted.
Sub SaveValuesOnly()
' 154
' list the sheets you want to keep by their tab names
Const SheetsToKeep As String = "Sheet1,Sheet3"
Dim sFileName As String
Dim sPath As String
Dim Wb As Workbook ' the new workbook
Dim Ws As Worksheet ' looping object: worksheet
Dim Keep() As String ' array of SheetsToKeep
Dim i As Long ' loop counter: Keep index
sPath = Environ("UserProfile") & "\Desktop\"
sFileName = "OVERALL RECAP"
Keep = Split(SheetsToKeep, ",")
With Application
.ScreenUpdating = False
.DisplayAlerts = False
End With
' create a copy of the ActiveWorkbook under a new name
ActiveWorkbook.SaveCopyAs sPath & sFileName & ".xlsm"
Set Wb = Workbooks.Open(sPath & sFileName & ".xlsm")
For Each Ws In Wb.Worksheets
' check if the sheet is to be kept
For i = UBound(Keep) To 0 Step -1
If StrComp(Ws.Name, Trim(Keep(i)), vbTextCompare) = 0 _
Then Exit For
Next i
If i = True Then ' True = -1
Ws.Delete
Else
' keep the sheet
With Ws.UsedRange
.Copy
.PasteSpecial xlPasteValuesAndNumberFormats
' you can repeat PasteSpecial here to copy more detail
End With
End If
Next Ws
' change the file format to xlsx (deleting copy of this code in it)
Wb.SaveAs Filename:=sPath & sFileName, FileFormat:=xlOpenXMLWorkbook
Kill sPath & sFileName & ".xlsm"
With Application
.ScreenUpdating = True
.DisplayAlerts = True
End With
End Sub
There are a few points you need to be aware of. One, the ActiveWorkbook will be copied. That is presumed to the ThisWorkbook (the one containing the code) but it could be any other. Two, any workbook by the targeted name already existing at the location specified by sPath will be over-written without warning. Three, alerts are turned off while the code runs. If it happens to crash they will remain turned off until you restart Excel or enter Application.DisplayAlerts = True [Enter] in the Immediate window.
Last, but not least, sheets are processed in sequence of their index numbers (left to right). If your formulas in the kept sheets refer to data in sheets that get deleted the sequence is important. You may have to run two loops instead of the one my code has. Use one loop to replace formulas and another just to delete.

Copying multiple sheets and renaming the worksheet

I want to copy multiple sheets from one workbook(4 out of 14) but i'm starting with one("Data"). I want to rename the workbook based on a cell in the first workbook. with this code I get an "run-time error '1004' Excel cannot access the file 'C:\3B4DD....
my code so far:
Sub Newyeartest()
sheetstocopy = "data"
Worksheets(sheetstocopy).Copy
Dim FName As String
Dim FPath As String
FPath = "C:"
FName = Sheets("data").Range("A1") & ".xlsm"
ThisWorkbook.SaveAs Filename:=FPath & "\" & FName, FileFormat:=52
End sub
If I delete the "Fileformat:=52" It seems to go better but I get a text that this file must be saved as an macro enabled file. But I would guess that "Xlsm" is macro enabled?
Instead of copying worksheets, the better way is to copy the workbook with all the worksheets and then delete the ones that are not needed.
The code saves the workbook first, using the path of the current workbook;
Then it starts checking every worksheet, making sure that the name is not "data";
If the name is not "data" and there are more than 1 worksheets left, it deletes the worksheet;
The Application.DisplayAlerts = False is needed, in order to remove the msgbox for confirmation of the deletion of the worksheet. Then the Alerts are back set to True;
If the name is not "data" and this is the last worksheet, it gives a MsgBox "Last worksheet cannot be deleted!", as far as a workbook should always have at least 1 worksheet, by design;
Sub NewTest()
ThisWorkbook.SaveAs ThisWorkbook.Path & "\new.xlsm"
Dim sheetToCopy As String: sheetToCopy = "data"
Dim wks As Worksheet
For Each wks In ThisWorkbook.Worksheets
If wks.Name <> sheetToCopy Then
If ThisWorkbook.Worksheets.Count > 1 Then
Application.DisplayAlerts = False
ThisWorkbook.Worksheets(wks.Name).Delete
Application.DisplayAlerts = True
Else
MsgBox "Last worksheet cannot be deleted!"
End If
End If
Next wks
End Sub
This should do the trick:
Option Explicit
Sub Newyeartest()
Dim wb As Workbook
Dim SheetNames As Variant, Key As Variant
Dim FName As String, FPath As String
Application.ScreenUpdating = False
SheetNames = Array("data", "data2", "data3", "data4") 'store the sheet names you want to copy
Set wb = Workbooks.Add 'set a workbook variable which will create a new workbook
'loop through the sheets you previously stored to copy them
For Each Key In SheetNames
ThisWorkbook.Sheets(Key).Copy After:=wb.Sheets(wb.Sheets.Count)
Next Key
'delete the first sheet on the new created workbook
Application.DisplayAlerts = False
wb.Sheets(1).Delete
FPath = "C:\Test"
FName = ThisWorkbook.Sheets("data").Range("A1") & ".xlsm"
wb.SaveAs Filename:=FPath & "\" & FName, FileFormat:=52
With Application
.ScreenUpdating = True
.DisplayAlerts = True
End With
End Sub
You cannot save directly to C:\ so you need to create a folder and the code will work.

VBA. Export only visible sheet to individual workbook

Sub SaveShtsAsBook()
‘Select all visible and hide sheet’
Dim Sheet As Worksheet, SheetName$, MyFilePath$, N&
MyFilePath$ = ActiveWorkbook.Path & "\" & _
Left(ThisWorkbook.Name, Len(ThisWorkbook.Name) - 4)
With Application
.ScreenUpdating = False
.DisplayAlerts = False
' End With
On Error Resume Next '<< a folder exists
MkDir MyFilePath '<< create a folder
For N = 1 To Sheets.Count
Sheets(N).Activate
SheetName = ActiveSheet.Name
Cells.Copy
Workbooks.Add (xlWBATWorksheet)
With ActiveWorkbook
With .ActiveSheet
.Paste
.Name = SheetName
[A1].Select
End With
'save book in this folder
.SaveAs Filename:=MyFilePath _
& "\" & SheetName & ".xlsx"
.Close SaveChanges:=True
End With
.CutCopyMode = False
Next
End With
Sheet1.Activate
End Sub
I have a workbook, that contains many sheets which have visible and hide ones. I only want to export each visible sheet to individual workbook. this current code above can do the export for all the sheet in the workbook but I have to delete them 1 by 1 after that. Hope that explains my situation.
All you need to add to your code to exclude hidden sheets is a simple If..Then statement to check whether the Worksheet.Visible property is True or False.
If Not yourWorsheet.Visible Then... ... then you skip that worksheet.
The following procedure is a simpler overall approach to what you're trying to accomplish...
Export Visible worksheets to their own workbooks:
The worksheet.Copy method will create a new workbook if neither Before nor After are specified.
Sub saveVisibleSheetsAsXLSM() 'saves all visible sheets as new xlsx files
Const exportPath = "x:\yourDestinationPath\"
Dim ws As Worksheet, wbNew As Workbook
For Each ws In ThisWorkbook.Sheets 'for each worksheet
If ws.Visible Then 'if it's visible:
Debug.Print "Exporting: " & ws.Name
ws.Copy '(if no params specified, COPY creates + activates a new wb)
Set wbNew = Application.ActiveWorkbook 'get new wb object
wbNew.SaveAs exportPath & ws.Name & ".xlsm", 52 'save new wb
wbNew.Close 'close new wb
Set wbNew = Nothing 'cleanup
End If
Next ws
Set ws = Nothing 'clean up
End Sub
Worksheet.Copy Remarks:
If you don't specify either Before or After, Microsoft Excel creates a new workbook that contains the copied sheet object that contains the copied Worksheet object. The newly created workbook holds the Application.ActiveWorkbook Property (Excel) property and contains a single worksheet. The single worksheet retains the Worksheet.Name Property (Excel) and Worksheet.CodeName Property (Excel) properties of the source worksheet. If the copied worksheet held a worksheet code sheet in a VBA project, that is also carried into the new workbook.
An array selection of multiple worksheets can be copied to a new blank Workbook Object (Excel) object in a similar manner.
(Source: Documentation)

Trying to copy a table to csv file and name it using original file name

I'm new to VBA and stuck on an issue. I'm trying to copy a table to a .csv file and I want the end result to contain the original .xlsm name & the table name and date/time. I've successfully pieced together code to export the table to .csv with the table name and date/time but I'm struggling to get the file mane in there. I get the following error "Method 'SaveAs' of object'_Workbook' failed"
Below is what I have, any help would be great!
Sub ExportTableBanquetEarnings()
Application.ScreenUpdating = False
Sheets("BanquetEarnings").Visible = True
Sheets("BanquetEarnings").Select
Dim wb As Workbook, wbNew As Workbook
Dim ws As Worksheet, wsNew As Worksheet
Dim wbNewName As String
Dim wbCurrent As String
wbCurrent = ThisWorkbook.FullName
Set wb = ThisWorkbook
Set ws = ActiveSheet
Set wbNew = Workbooks.Add
With wbNew
Set wsNew = wbNew.Sheets("Sheet1")
wbNewName = ws.ListObjects(1).Name
ws.ListObjects(1).Range.Copy
wsNew.Range("A1").PasteSpecial Paste:=xlPasteAll
.SaveAs Filename:="F:\admin\Report Databases\BanquetTipouts" & "\" &
wbCurrent & wbNewName & Format(Now, "yyyymmdd_hhmm") & ".csv", _
FileFormat:=xlCSVMSDOS, CreateBackup:=False
End With
Application.DisplayAlerts = False
ActiveWorkbook.Close
Application.DisplayAlerts = True
ActiveWorkbook.RefreshAll
Sheets("BanquetEarnings").Visible = False
Sheets("Blank Cost Sheet").Select
Workbooks.Open "F:\Function Agreements\Cost Sheets M\Payroll Report -
V2.xlsm"
End Sub
The below code will show the path of that Workbook
wbCurrent = ThisWorkbook.FullName
I think what you meant to use is...
wbCurrent = ThisWorkbook.Name
Also, I think another issue might be the Now method, it should be as Now()

Export multiple worksheets to CSV files in a specified directory

I'm trying to do the following:
Export/Copy particular sheets in the workbook (any sheet name that contains "Upload") to a particular file directory.
I don't want these worksheet names to change nor the workbook name to change.
The file-name is consistent for each worksheet, so it would be okay to replace the files in the directory whenever I run the macro. It is okay to have a dialog box that asks if I'm sure I want to replace each of the files.
I don't want the newly created CSVs or any other file to open.
Sub SheetsToCSV()
'Jerry Beaucaire (1/25/2010), updated (8/15/2015)
'Save each sheet to an individual CSV file
Dim ws As Worksheet, fPATH As String
Application.ScreenUpdating = False 'speed up macro
Application.DisplayAlerts = False 'automatically overwrite old files
fPATH = "C:\2015\CSV\" 'path to save into, remember the final \ in this string
For Each ws In Worksheets
ws.Copy
ActiveWorkbook.SaveAs Filename:=fPATH & ActiveSheet.Name & ".csv", FileFormat:=xlCSV, CreateBackup:=False
ActiveWorkbook.Close
Next ws
Application.ScreenUpdating = True
End Sub
You just need to add a simple loop through all worksheets and test the name.
Try this:-
Sub COPYSelectedSheetsToCSV()
Dim ws As Worksheet
'In case something goes wrong
On Error GoTo COPYSelectedSheetsToCSVZ
'Loop through all worksheets
For Each ws In ActiveWorkbook.Sheets
'Does the name contain "Upload"
If InStr(1, ws.Name, "Upload") > 0 Then
'Make the worksheet active
ws.Select
'Save it to CSV
ActiveWorkbook.SaveAs Filename:="/Users/reginaho/Desktop/Upload/" & ws.Name & ".csv", _
FileFormat:=xlCSV, CreateBackup:=False
End If
Next
COPYSelectedSheetsToCSVX:
'Clean up the memory usage
Set ws = Nothing
Exit Sub
COPYSelectedSheetsToCSVZ:
MsgBox Err.Number & " - " & Err.Description
Resume COPYSelectedSheetsToCSVX
End Sub

Resources