Copy The Code from one sheet to another - vba

I am trying to write a code that create another sheet and paste the code of the second sheet on it, the program also will delete the sheet if it already exists
Application.DisplayAlerts = False
Sheets("Calcs").Delete
Application.DisplayAlerts = True
With ThisWorkbook
.Sheets.Add(after:=.Sheets(.Sheets.Count)).Name = "Calcs"
End With
Dim CodeCopy As VBIDE.CodeModule
Dim CodePaste As VBIDE.CodeModule
Dim numLines As Integer
Set CodeCopy = ActiveWorkbook.VBProject.VBComponents("Sheet2").CodeModule
Set CodePaste = ActiveWorkbook.VBProject.VBComponents("Calcs").CodeModule
numLines = CodeCopy.CountOfLines
CodePaste.AddFromString CodeCopy.Lines(1, numLines)
Is not working and I dont know why

I think it's not working because of the name of your sheet. In the VBA Project window you can see that your sheets have two names: Sheet1 (Sheet1). So when you add your sheet and rename it, the name will be Sheet##(Calcs) but when you write ActiveWorkbook.VBProject.VBComponents("Calcs").CodeModule you need to use "Sheet##" which is the codename instead of "Calcs".
It is better explained here:
Excel tab sheet names vs. Visual Basic sheet names
What I suggest is to declare your sheet when you create it and write ...VBComponents(TheNameYouDeclared.CodeName).CodeModule
The code you gave us plus what I suggest gives you:
Application.DisplayAlerts = False
Sheets("Calcs").Delete
Application.DisplayAlerts = True
With ThisWorkbook
.Sheets.Add(after:=.Sheets(.Sheets.Count)).Name = "Calcs"
End With
Dim MySheet As Worksheet
Set MySheet = ThisWorkbook.Sheets("Calcs")
Dim CodeCopy As String
Dim CodePaste As String
Dim numLines As Integer
CodeCopy = ActiveWorkbook.VBProject.VBComponents("Sheet1").CodeModule
CodePaste = ActiveWorkbook.VBProject.VBComponents(MySheet.CodeName).CodeModule
numLines = CodeCopy.CountOfLines
CodePaste.AddFromString CodeCopy.Lines(1, numLines)
Is it working for you?

Create a template worksheet containing the code you need - then just copy this to create your new sheet.
In my code I have used the codename of the template sheet rather than the name that appears on the tab (which can be changed outside the VBE) - it's the name not in brackets in your Microsoft Excel Objects and can be updated with the (Name) property in the Properties tab.
Sub Test()
If WorkSheetExists("Calcs") Then
Application.DisplayAlerts = False
ThisWorkbook.Worksheets("Calcs").Delete
Application.DisplayAlerts = True
End If
With shtTemplate 'Use codename rather than actual name.
.Visible = xlSheetVisible
.Copy After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
.Visible = xlSheetVeryHidden
End With
ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count).Name = "Calcs"
End Sub
Public Function WorkSheetExists(SheetName As String, Optional WrkBk As Workbook) As Boolean
Dim wrkSht As Worksheet
If WrkBk Is Nothing Then
Set WrkBk = ThisWorkbook
End If
On Error Resume Next
Set wrkSht = WrkBk.Worksheets(SheetName)
WorkSheetExists = (Err.Number = 0)
Set wrkSht = Nothing
On Error GoTo 0
End Function

Related

How to make this code not rely on the file name

I have this code that pulls data from 4 separate workbooks and paste them into the next empty section in a template workbook (FRF_Data_Macro_Insert_Test). This works perfectly but i have one issue, I need it to be able to paste in the active workbook and not to be dependent on the file name. Because this is a template and therefore read only, it prompts you to save as a different file name upon opening. I told the people using this to just cancel the first save as window and just save as when all done pulling data but they keep saving as before they pull data making it not work because its looking for FRF_Data_Macro_Insert_Test filename. Any help is much appreciated!
Thanks
Code:
Sub DataTransfer()
Const FPATH As String = "C:\Users\aholiday\Desktop\FRF_Data_Macro_Insert_Test\"
Application.ScreenUpdating = False
Dim wb As Workbook
Dim shtAlpha As Worksheet 'Template
Dim locs, loc
Dim rngDest As Range
locs = Array("Location1.xls", "Location2.xls", _
"Location3.xls", "Location4.xls")
Set shtAlpha = Workbooks("FRF_Data_Sheet_Template.xlsm").Sheets("DataInput")
'set the first data block destination
Set rngDest = shtAlpha.Cells(Rows.Count, "C").End(xlUp).Offset(1, 0).Resize(5, 3)
For Each loc In locs
Set wb = Workbooks.Open(FileName:=FPATH & loc, ReadOnly:=True)
rngDest.Value = wb.Sheets("Data").Range("I3:K7").Value
wb.Close False
Set rngDest = rngDest.Offset(0, 3) 'move over to the right 3 cols
Next loc
Application.ScreenUpdating = True
End Sub
As your macro is in the workbook you want to reference, you can simply use ThisWorkbook:
Sub DataTransfer()
Const FPATH As String = "C:\Users\aholiday\Desktop\FRF_Data_Macro_Insert_Test\"
Application.ScreenUpdating = False
Dim wb As Workbook
Dim shtAlpha As Worksheet 'Template
Dim locs, loc
Dim rngDest As Range
locs = Array("Location1.xls", "Location2.xls", _
"Location3.xls", "Location4.xls")
Set shtAlpha = ThisWorkbook.Sheets("DataInput")
'set the first data block destination
Set rngDest = shtAlpha.Cells(Rows.Count, "C").End(xlUp).Offset(1, 0).Resize(5, 3)
For Each loc In locs
Set wb = Workbooks.Open(Filename:=FPATH & loc, ReadOnly:=True)
rngDest.Value = wb.Sheets("Data").Range("I3:K7").Value
wb.Close False
Set rngDest = rngDest.Offset(0, 3) 'move over to the right 3 cols
Next loc
Application.ScreenUpdating = True
End Sub
I would post this as just a comment, but it won't let me.
I'm not sure if i'm following what you're asking right, but if it's a matter of just saving a separate copy with a different name automatically, then itt would be Workbooks("FRF_Data_Sheet_Template.xlsm").SaveCopyAs

Excel VBA activate worksheet

I need to activate a specific worksheet. The code is meant to create worksheets with a specif name. I need to paste something from a another worksheet into all these newly created worksheets. The code that I'm using is below. But I'm having a hard time activating the newly created worksheet to paste what I want.
Sub octo()
'Dim ws As Worksheet
Dim Ki As Range
Dim ListSh As Range
Workbooks.Open ("C:\Users\Dash\Dropbox\Randika\Misc\Emmash timesheets\timesheet.xlsx")
With Worksheets("PPE 05-17-15")
Set ListSh = .Range("B4:B" & .Cells(.Rows.Count, "B").End(xlUp).Row)
End With
On Error Resume Next
For Each Ki In ListSh
If Len(Trim(Ki.Value)) > 0 Then
If Len(Worksheets(Ki.Value).Name) = 0 Then
Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = Ki.Value
'open template
Workbooks.Open ("C:\Users\Dash\Dropbox\Randika\Misc\Emmash timesheets\octo_template.xls")
Range("A1:L31").Select
Selection.Copy
Worksheets(Ki.Value).Activate
If ThisWorkbook.Saved = False Then
ThisWorkbook.Save
End If
End If
End If
Next Ki
End Sub
Both Workbooks.Open and Worksheets.Add return references to the opened and added objects, which you can use to directly access and modify them - and in your case, to paste data.
Example:
Dim oSourceSheet As Worksheet
Dim oTargetSheet As Worksheet
Set oSourceSheet = Sheet1 'Set reference to any sheet, Sheet1 in my example
Set oTargetSheet = Worksheets.Add(After:=Worksheets(Worksheets.Count))
oSourceSheet.Range("A1:L31").Copy
oTargetSheet.Paste
Set oSourceSheet = Nothing
Set oTargetSheet = Nothing
I think that is what you need. As what been mentioned by chris, there is no need Activate or Select. Hope the following code solve your problem.
Option Explicit
Dim MyTemplateWorkbook As Workbook
Dim MyDataWorkbook As Workbook
Dim MyTemplateWorksheet As Worksheet
Dim MyDataWorksheet As Worksheet
Dim MyNewDataWorksheet As Worksheet
Dim CurrentRange As Range
Dim ListRange As Range
Sub AddWSAndGetData()
Set MyTemplateWorkbook = Workbooks.Open("C:\Users\lengkgan\Desktop\Testing\MyTemplate.xlsx")
Set MyTemplateWorksheet = MyTemplateWorkbook.Sheets("Template")
Set MyDataWorkbook = Workbooks.Open("C:\Users\lengkgan\Desktop\Testing\MyData1.xlsx")
Set MyDataWorksheet = MyDataWorkbook.Sheets("PPE 05-17-15")
Set ListRange = MyDataWorksheet.Range("B4:B" & MyDataWorksheet.Cells(Rows.Count, "B").End(xlUp).Row)
Application.ScreenUpdating = False
On Error Resume Next
For Each CurrentRange In ListRange
If Len(Trim(CurrentRange.Value)) > 0 Then
If Len(MyDataWorksheet(CurrentRange.Value).Name) = 0 Then
Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = CurrentRange.Value
Set MyNewDataWorksheet = MyDataWorkbook.Sheets(ActiveSheet.Name)
MyNewDataWorksheet.Range("A1:L31").Value = MyTemplateWorksheet.Range("A1:L31").Value
If MyDataWorkbook.Saved = False Then
MyDataWorkbook.Save
End If
End If
End If
Next CurrentRange
MyTemplateWorkbook.Close (False) 'Close the template without saving
End Sub

How to import worksheet with desired columns? Excel VBA

I'm able to import worksheets successfully to my workbook. But is it possible to just import the columns that I want? The data is really huge and I don't want to have the trouble to go through every part of the cells.
Below are my codes:
Sub ImportSheet()
Dim wb As Workbook
Dim activeWB As Workbook
Dim sheet As Worksheet
Dim FilePath As String
Dim oWS As String
Set activeWB = Application.ActiveWorkbook
FilePath = "C:\Report.xlsx"
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set wb = Application.Workbooks.Open(FilePath)
wb.Sheets("Report").Copy After:=activeWB.Sheets(activeWB.Sheets.Count)
activeWB.Activate
wb.Close False
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
Not sure if I'm breaking protocol here but this is a completely different approach and the option to Add Another Answer was there. This method uses the 'copy to new worksheet' approach which should be easier on limited resources.
Sub ImportSheet()
Dim iWB As Workbook, aWB As Workbook, ws As Worksheet
Dim FilePath As String, v As Long, vCOLs As Variant
Application.ScreenUpdating = False
Application.DisplayAlerts = False
FilePath = "C:\Report.xlsx"
vCOLs = Array(1, 13, 6, 18, 4, 2) 'columns to copy in this order
Set aWB = Application.ActiveWorkbook
With aWB
.Sheets.Add after:=.Sheets(.Sheets.Count)
Set ws = .Sheets(.Sheets.Count)
'.name = "Report" 'you can name the new ws but do NOT duplicate
End With
Set iWB = Application.Workbooks.Open(FilePath)
With iWB.Sheets("Report").Cells(1, 1).CurrentRegion
.Cells = .Cells.Value
For v = LBound(vCOLs) To UBound(vCOLs)
.Columns(vCOLs(v)).Copy Destination:=ws.Cells(1, v + 1)
Next v
End With
iWB.Close False
Set iWB = Nothing
Set ws = Nothing
Set aWB = Nothing
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
My primary concern here is not knowing the layout of the 'Report' worksheet. The boundaries of the .CurrentRegion are dictated by the first fully blank column to the right and the first fully blank row down. A block of data rarely has this but worksheets called Report often do.
You are closing the freshly opened workbook (without saving or warnings) after the copy so I would suggest that you loop through the columns you do not want and delete then prior to the copy. Incorporate this snippet into your existing code
Dim v As Long, vNoCopy As Variant, wb As Workbook
vNoCopy = Array(1, 3, 5, 7) 'should in ascending order (reversed below)
With wb.Sheets("Report")
.Cells = .Cells.Value 'just in case there are referenced formulas involved
For v = UBound(vNoCopy) To LBound(vNoCopy) Step -1
.Columns(vNoCopy(v)).EntireColumn.Delete
Next v
wb.Sheets("Report").Copy After:=activeWB.Sheets(activeWB.Sheets.Count)
End With
wb.Close False
That should remove columns A, C, E & G from the report before copying. Closing without saving should leave the original Report.xlsx unaffected.

Excel 2013 VBA Sheets.Add doesn't return new sheet?

So my code was working fine, until IT upgraded me to Excel 2013 and the SDI interface. Now it looks like the Sheets.Add function doesn't return the proper worksheet. The template is added to the correct workbook (Template1) but when I use the returned worksheet, it's referencing a sheet from the active workbook, before all the VBA code ran.
Public Function Worksheet_AddTemplate(TargetBook As Excel.Workbook, _
TemplateFile as String) As Excel.Worksheet
Dim ws As Excel.Worksheet
Debug.Print TargetBook.Name 'Output-->Template1
Set ws = TargetBook.Sheets.Add( _
After:=TargetBook.Sheets(TargetBook.Sheets.Count), _
Type:=TemplateFile)
Debug.Print ws.Parent.Name 'Output-->Book1
Set Worksheet_AddTemplate = ws
Set ws = Nothing
End Function
Can someone else verify that this is happening to you with Excel 2013, and that there isn't something that I'm missing here.
Thanks
P.S. I use a similar routine to create the template workbook/first sheet with no issues.
Edit: The Code is being called from an Add-In. Here is how I call the Function, more or less (I've simplified the routines because it would be too long otherwise)
Private Sub ImportDataFile()
Dim wb As Excel.Workbook
Dim ws As Excel.Worksheet
Dim sUnit As String, sTemplateFile As String
Dim u As Integer, nUnits As Integer
Application.ScreenUpdating = False
Application.EnableEvents = False
' ...Some setup stuff that I wont bother you with
sTemplateFile = Environ("Temp") & "\Template1.xlt"
For u = 0 To nUnits - 1
If wb Is Nothing Then
Set wb = Workbook_NewTemplate(sTemplateFile)
Set ws = wb.Worksheets(1)
Else
Set ws = Worksheet_AddTemplate(wb, sTemplateFile)
End If
ws.range("H6") = sUnit
' More Loops & writing to cells
For i = 0 To g_Data(f).ItemCount - 1
' Blah, blah, blah
Next
Next
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
I've noticed that if I add 2x DoEvents anywhere in between creating the workbook and adding the second sheet it will work as it did before.
Also, if I use this code in the Worksheet_AddTemplate function it seems to work...
Set wb = Application.Workbooks.Add(Template:=TemplateFile)
Set ws = wb.Worksheets(1)
ws.Copy After:=TargetBook.Sheets(TargetBook.Sheets.Count)
Set ws = TargetBook.Sheets(TargetBook.Sheets.Count)

How to define an object inside a for loop for excel vba

I want to import data from multiple workbooks, all from the same sheet index (3).
I'm new to vba, and I figured out how to open multiple files up, and also to copy data from one sheet to another sheet in a different workbook for a single file, but I can't seem to figure out how to do that for multiple files.
I highlighted where the error is, it tells me "object doesn't support this property or method"
Could you please help?
Thanks
Sub dataimport()
' Set Vars
Dim ArbinBook As Workbook, DataBook As Workbook
Dim i As Integer, j As Integer
Dim Caption As String
Dim ArbinFile As Variant, DataFile As Variant
' make weak assumption that active workbook is the target
Set DataBook = Application.ActiveWorkbook
' get Arbin workbook
Caption = "Please select an input file"
' To set open destination:
' ChDrive ("E")
' ChDir ("E:\Chapters\chap14")
' With Application
'Set "arbinfile" as variant, the "true" at end makes it into an array
ArbinFile = Application.GetOpenFilename(, , Caption, , True)
'Exit when canceled
If Not IsArray(ArbinFile) Then
MsgBox "No file was selected."
Exit Sub
End If
Dim targetSheet As Worksheet
Set targetSheet = DataBook.Sheets(1)
'Open for every integer i selected in the array "arbinfile"
For i = LBound(ArbinFile) To UBound(ArbinFile)
Set ArbinBook = Workbooks.Open(ArbinFile(i))
targetSheet.Range("A2", "G150").Value = ArbinBook.Sheets(3).Range("A2", "G150").Value
**ERROR at the line above**
Workbooks(DataSheet).Activate 'Reactivate the data book
Worksheets(1).Activate 'Reactivate the data sheet
ActiveWorkbook.Sheets(1).Copy _
after:=ActiveWorkbook.Sheets(1)
Workbooks(ArbinFile(1)).Activate 'Reactivate the arbin book(i)
ArbinBook.Close
Next i
Beep
End Sub
My instinct tells me that ArbinBook.Sheets(3) is a Chart-sheet, not a WorkSheet (or, at least, it is something other than a WorkSheet). It might be hidden as well, but it will still be indexed as (3).
If so, change Sheets(3) to Worksheets(3).
Added: BTW If true, this also demonstrates why using index-numbers is unreliable. If at all possible, refer to a worksheet by its name. (I appreciate that this may not always be possible.)
Added (from comments) There is nothing named DataSheet in your code. Add Option Explicit to the top of your module to indicate all such errors.
Try changing the line Set ArbinBook = Workbooks.Open(ArbinFile(i))
to Set ArbinBook = Workbooks(arbinfile(i))
I could be wrong, but I think it's trying to set your workbook object to become the action of opening another workbook, instead of labeling it as the workboook.
Sub Multiple()
Application.DisplayAlerts = False
Application.EnableEvents = False
Dim exlApp As Excel.Application
Dim exlWb1 As Excel.Workbook
Dim exlWb2 As Excel.Workbook
Dim exlWb3 As Excel.Workbook
Dim exlWs1 As Excel.Worksheet
Dim exlWs2 As Excel.Worksheet
Dim exlWs3 As Excel.Worksheet
Set exlApp = CreateObject("Excel.Application")
Set exlWb1 = exlApp.Workbooks.Open("C:\yourpath1\file1.xls")
Set exlWb2 = exlApp.Workbooks.Open("C:\yourpath2\file2.xls")
Set exlWb3 = exlApp.Workbooks.Open("C:\yourpath3\file3.xls")
Set exlWs1 = exlWb.Sheets("Sheet1")
Set exlWs2 = exlWb.Sheets("Sheet1")
Set exlWs3 = exlWb.Sheets("Sheet1")
exlWb1.Activate
exlWb2.Activate
exlWb3.Activate
'code
exlWb.Close savechanges:=True
exlWb.Close savechanges:=True
exlWb.Close savechanges:=True
Set exlWs1 = Nothing
Set exlWs2 = Nothing
Set exlWs3 = Nothing
Set exlWb1 = Nothing
Set exlWb2 = Nothing
Set exlWb3 = Nothing
exlApp.Quit
Set exlApp = Nothing
Application.EnableEvents = True
Application.DisplayAlerts = True
End Sub