Embed Chart Template into Macro - vba

I am trying to embed applying a chart template into a macro and require help.
I have this code for the Macro that I am using to create scatter plots:
Option Explicit
Public Sub Test()
' Keyboard Shortcut: Ctrl+Shift+X
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Sheet1") 'change as appropriate
Application.ScreenUpdating = False
BuildChart ws, SelectRanges(ws)
Application.ScreenUpdating = True
End Sub
Private Function SelectRanges(ByRef ws As Worksheet) As Range
Dim rngX As Range
Dim rngY As Range
ws.Activate
Application.DisplayAlerts = False
On Error Resume Next
Set rngX = Application.InputBox("Please select X values. One column.",
Type:=8)
If rngX Is Nothing Then GoTo InvalidSelection
Set rngY = Application.InputBox("Please select Y values. One column.",
Type:=8)
If rngY Is Nothing Then GoTo InvalidSelection
If rngX.Columns.Count > 1 Or rngY.Columns.Count > 1 Then GoTo
InvalidSelection
On Error GoTo 0
Set SelectRanges = Union(rngX, rngY)
Application.DisplayAlerts = True
Exit Function
InvalidSelection:
If rngX Is Nothing Or rngY Is Nothing Then
MsgBox "Please ensure you have selected both X and Y ranges."
ElseIf rngX.Rows.Count <> rngX.Rows.Count Then
MsgBox "Please ensure the same number of rows are selected for X and Y
ranges"
ElseIf rngX.Columns.Count > 1 Or rngY.Columns.Count > 1 Then
MsgBox "Please ensure X range has only one column and Y range has only
one column"
Else
MsgBox "Unspecified"
End If
Application.DisplayAlerts = True
End
End Function
Private Sub BuildChart(ByRef ws As Worksheet, ByRef unionRng As Range)
With ws.Shapes.AddChart2(240, xlXYScatter).Chart
.SetSourceData Source:=unionRng
End With
ActiveChart.ApplyChartTemplate ( _
"C:\Users\maaro\AppData\Roaming\Microsoft\Templates\Charts\1.crtx")
End Sub
And would like to embed this code below into the above code so that it applies the template to the chart I create whenever I run this Macro. My initial guess would be to put it underneath "Private Sub BuildCharts". How would I be able to do this? Thank you.
ActiveChart.ApplyChartTemplate ( _
"C:\Users\XXXXX\AppData\Roaming\Microsoft\Templates\Charts\1.crtx")

Perhaps modify Sub BuildChart like this:
Private Sub BuildChart(ByRef ws As Worksheet, ByRef unionRng As Range)
With ws.Shapes.AddChart2(240, xlXYScatter).Chart
.SetSourceData Source:=unionRng
.ApplyChartTemplate ( _
"C:\Users\maaro\AppData\Roaming\Microsoft\Templates\Charts\1.crtx")
End With
End Sub

Related

Setting all selected sheets to same visible area

Attempting a macro that will set all selected sheets to have same cells visible as in the active sheet.
Example: if top-left cell is L76 on active sheet, then running this macro will set all selected worksheets to show L76 as the top left cell.
Cobbled this code together from examples found online but not sufficiently advanced in VBA to make it work.
Sub SetAllSelectedSheetsToSameRowColCell()
Dim rngSel As Range
Dim intScrollCol As Integer
Dim intScrollRow As Long
Dim oSheet As Object
If TypeName(Sh) = "Worksheet" Then
Set oSheet = ActiveSheet
Application.EnableEvents = False 'Unsure what this line is for
Sh.Activate
With ActiveWindow
intScrollCol = .ScrollColumn
intScrollRow = .ScrollRow
Set rngSel = .RangeSelection
End With
oSheet.Activate
Application.EnableEvents = True
End If
'Loop thru rest of selected sheets and update to have same cells visible
Dim oWs As Worksheet
For Each oWs In Application.ActiveWindow.SelectedSheets
On Error Resume Next
oWs.Range(rngSel.Address).Select
.ScrollColumn = intScrollCol
.ScrollRow = intScrollRow
Next
End Sub
References:
https://excel.tips.net/T003860_Viewing_Same_Cells_on_Different_Worksheets.html
VBA Macro To Select Same Cell on all Worksheets
Try this:
Sub ResetAllSheetPerspectives()
Dim ws As Worksheet
Dim lRow As Long
Dim lCol As Long
Dim dZoom As Double
lRow = ActiveWindow.ScrollRow
lCol = ActiveWindow.ScrollColumn
dZoom = ActiveWindow.Zoom
For Each ws In Application.ActiveWindow.SelectedSheets
ws.Activate
ActiveWindow.Zoom = dZoom
Application.Goto ws.Cells(lRow, lCol), True
Next ws
End Sub
Maybe this will help. Sets the top left cell of other sheets depending on the first sheet.
Sub Macro1()
Dim r As Range, ws As Worksheet
Sheets(1).Activate
Set r = ActiveWindow.VisibleRange.Cells(1)
For Each ws In Worksheets
If ws.Index > 1 Then
ws.Activate
ActiveWindow.ScrollRow = r.Row
ActiveWindow.ScrollColumn = r.Column
End If
Next ws
End Sub
This procedure sets the same visible range as the active worksheet for all selected worksheets. It excludes any Chart sheet in the selection and adjusts the zoom of the selected sheets to ensure all worksheets have the same visible area.
Sub SelectedWorksheets_ToSameVisibleRange()
Dim ws As Worksheet
Dim oShs As Object, oSh As Object
Dim sRgAddrs As String
On Error Resume Next
Set ws = ActiveSheet
On Error GoTo 0
If ws Is Nothing Then
MsgBox "Active sheet must be a worksheet type" & String(2, vbLf) _
& String(2, vbTab) & "Process will be cancelled.", _
vbCritical, "Worksheets Common Range View"
Exit Sub
End If
With ActiveWindow
Set oShs = .SelectedSheets
sRgAddrs = .VisibleRange.Address 'Get address of Active Sheet visible range
End With
For Each oSh In oShs
If TypeName(oSh) = "Worksheet" And oSh.Name <> ws.Name Then 'Excludes any chart sheet and the active sheet
With oSh.Range(sRgAddrs)
Application.Goto .Cells, 1 'Activate Worksheet targeted visible range
ActiveWindow.Zoom = True 'Zoom Worksheet to make visible same range as the "active worksheet"
Application.Goto .Cells(1), 1 'Activate 1st cell of the visible range
End With: End If: Next
ws.Select 'Ungroups selected sheets
End Sub

Updating my workbook

I have created a Workbook that is used in various different computers.
Sometimes I add features to it and I would like to easily update it.
The idea is whenever I have a new version of it, I take it to a new computer, save in a temp file and copy the sheets where the data is stored.
Based on the answers I have edit my first draft to: (I didn't know that both workbooks needed to be opened at the same time)
Private Sub CommandButton1_Click()
Dim sh As Worksheet
Dim ws As Worksheet
Dim wb As Workbook
Dim wn As Workbook
Set wn = Workbooks("Reception")
Set wb = Workbooks("Reception2")
With wb
.Sheets("Pass").Range("A1") = "flh"
For Each ws In .Worksheets
Select Case .Name
Case "Formularios", "Coordenador", "LookupList", "Pass"
'Do nothing
Case Else
ws.Delete
End Select
Next ws
End With
With wn
For Each sh In .Worksheets
Select Case .Name
Case "Formularios", "Coordenador", "LookupList", "Pass"
'Do nothing
Case Else
sh.Copy After:=wb.Sheets(wb.Sheets.Count)
End Select
Next sh
End With
End Sub
Case at moment is not working and macro deletes every sheet no matter the name
Thank you all for the feedback
You can find the temp folder by using Environ("temp"), but from your code I'm not sure this is the folder you're using.
This code has a couple of functions to check if the workbook exists and is already open. One other bit of code I'd add is to disable any code in Reception.xlsm from firing when it's opened.
Public Sub MyProcedure()
Dim ws As Worksheet
Dim wb As Workbook
Dim wn As Workbook
Dim Rec1Path As String
Dim Rec2Path As String
Rec1Path = "c:\save\Reception.xlsm"
Rec2Path = "c:\temp\Reception2.xlsm"
'Open or set a reference to Reception.xlsm.
If WorkBookExists(Rec1Path) Then
If WorkBookIsOpen(Rec1Path) Then
'Don't need path for open workbook, just name.
'InStrRev finds last occurrence of "\" (same as InStr, but in Reverse).
Set wn = Workbooks(Mid(Rec1Path, InStrRev(Rec1Path, "\") + 1))
Else
Set wn = Workbooks.Open(Rec1Path)
End If
End If
'Open or set a reference to Reception2.xlsm.
If WorkBookExists(Rec2Path) Then
If WorkBookIsOpen(Rec2Path) Then
Set wb = Workbooks(Mid(Rec2Path, InStrRev(Rec2Path, "\") + 1))
Else
Set wb = Workbooks.Open(Rec2Path)
End If
End If
With wb
.Worksheets("Pass").Range("A1") = "flh"
For Each ws In .Worksheets
Select Case .Name
Case "Formularios", "Coordenador", "LookupList", "Pass"
'Do nothing
Case Else
'You don't really need the count of worksheets if you can guarantee
'you're not going to try and delete the last remaining sheet.
If .Worksheets.Count > 1 Then
Application.DisplayAlerts = False
ws.Delete
Application.DisplayAlerts = True
End If
End Select
Next ws
End With
With wn
'Re-using the ws variable.
For Each ws In .Worksheets
Select Case .Name
Case "Formularios", "Coordenador", "LookupList", "Pass"
'Do nothing
Case Else
ws.Copy After:=wb.Sheets(wb.Sheets.Count)
End Select
Next ws
End With
End Sub
Public Function WorkBookExists(sPath As String) As Boolean
WorkBookExists = Dir(sPath) <> ""
End Function
Public Function WorkBookIsOpen(FullFilePath As String) As Boolean
Dim ff As Long
On Error Resume Next
ff = FreeFile()
Open FullFilePath For Input Lock Read As #ff
Close ff
WorkBookIsOpen = (Err.Number <> 0)
On Error GoTo 0
End Function
Is the workbook open when you try to 'SET' it? If not you will need to open it as such:
Dim wb As Workbook
Set wb = Workbooks.Open("c:\temp\Reception.xlsm")
With some more googling I was able to craft the code that I wanted in the end.
Here is the answer for the curious or for other people looking to do the same:
Private Sub CommandButton1_Click()
Dim sh As Worksheet
Dim ws As Worksheet
Dim LastRow As Long
Dim LastCol As Long
Dim j As Long
Dim Rng As Range
Dim wb As Workbook
Dim wn As Workbook
Set wn = Workbooks("Reception")
Set wb = Workbooks("Reception2")
With wb
.Sheets("Pass").Range("A1") = "flh"
For Each ws In .Worksheets
Select Case ws.Name
Case "Formularios"
'Do nothing
Case "Coordenador"
'Do nothing
Case "LookupList"
'Do nothing
Case "Pass"
'Do nothing
Case Else
With ws
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
Set Rng = .Range(.Cells(2, 1), .Cells(LastRow, LastCol))
Rng.ClearContents
End With
End Select
Next ws
End With
With wn
For Each sh In .Worksheets
Select Case sh.Name
Case "Formularios"
'Do nothing
Case "Coordenador"
'Do nothing
Case "LookupList"
'Do nothing
Case "Pass"
'Do nothing
Case Else
For j = 1 To wb.Sheets.Count
If sh.Name = wb.Worksheets(j).Name Then
On Error Resume Next
sh.Range("A:J").Copy wb.Worksheets(j).Range("A1")
End If
Next j
End Select
Next sh
End With
Application.CutCopyMode = False
End Sub
Thanks to #Darren Bartrup-Cook for the help.

Code to allow user make range selection to search list in another workbook and return cell value

Info
Workbook A: Has a master worksheet with a list of items, but the values are arranged in month columns
Workbook B: I have two sheets with different list of items I want to use to search Workbook A and return the current or specific month I need.
Note: Workbook B columns is offset, so we may need to account for this.
The code I have so far:
Sub Button()
Dim OpenFileName As String
Dim MyWB As Workbook, wb As Workbook
Dim aRange As Range
'Excel titled, "MODs", contains this module
Set MyWB = ThisWorkbook
'Ignore possible messages on a excel that has links
Application.AskToUpdateLinks = False
Application.DisplayAlerts = False
'Select and Open workbook
OpenFileName = Application.GetOpenFilename '("clients saved spreadsheet,*.xlsb")
If OpenFileName = "False" Then Exit Sub
Set wb = Workbooks.Open(OpenFileName)
Application.DisplayAlerts = True
Application.AskToUpdateLinks = True
If MsgBox("Please select list range to search.", vbExclamation, "Search List") = vbOK Then
On Error Resume Next
Set aRange = Application.InputBox(prompt:="Enter range", Type:=8)
If aRange Is Nothing Then
MsgBox "Operation Cancelled"
Else
aRange.Select
End If
End If
End Sub
I might might be making this harder than I should be, so I am open to suggestions. I can't seem to find the right find function to use my selected range list and target the newly open workbook with the specific master worksheet (something similar to a vlookup).
Version 2: with a set range but I'm still getting not value returns
Sub Button()
Dim OpenFileName As String
Dim MyWB As Workbook, wb As Workbook
Dim MyWs As Worksheet, ws As Worksheet
Dim aRange As Range
'This line of code turns off the screen updates which make the macro run much faster.
'Application.ScreenUpdating = False
'Excel titled, "MODs", contains this module
Set MyWB = ThisWorkbook
Set MyWs = MyWB.Sheets("Sheet")
'Ignore possible messages on a excel that has links
Application.AskToUpdateLinks = False
Application.DisplayAlerts = False
'Select and Open workbook
OpenFileName = Application.GetOpenFilename '("clients saved spreadsheet,*.xlsb")
If OpenFileName = "False" Then Exit Sub
Set wb = Workbooks.Open(OpenFileName)
On Error Resume Next
Set ws = Application.InputBox("Select a cell on the key sheet.", Type:=8).Parent
On Error GoTo 0
If ws Is Nothing Then
MsgBox "cancelled"
Else
MsgBox "You selected sheet " & ws.Name
End If
Application.DisplayAlerts = True
Application.AskToUpdateLinks = True
With MyWs
For Each aCell In .Range("A1:A10" & LastRow)
If Len(Trim(.Range("A19" & aCell.Row).Value)) <> 0 Then
.Cells(aCell.Row, 15) = Application.WorksheetFunction.VLookup( _
aCell.Value, ws.Range("A1:C18"), 2, 0)
End If
Next aCell
End With
'wb.Close (False)
'If MsgBox("Please select list range to search.", vbExclamation, "Search List") = vbOK Then
'On Error Resume Next
'Set aRange = Application.InputBox(prompt:="Enter range", Type:=8)
'If aRange Is Nothing Then
'MsgBox "Operation Cancelled"
'Else
'aRange.Select
'End If
'End If
'Return to default setting of screen updating.
'Application.ScreenUpdating = True
End Sub
I think the problem I'm running into is this code:
With MyWs
For Each aCell In .Range("A1:A10" & LastRow)
If Len(Trim(.Range("A19" & aCell.Row).Value)) <> 0 Then
.Cells(aCell.Row, 15) = Application.WorksheetFunction.VLookup( _
aCell.Value, ws.Range("A1:C18"), 2, 0)
begin declaringaCell as Range and lastRow as long
You seem to miss the definition of lastRow, which could be something like
lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
then look carefully at .Range("A1:A10" & LastRow). Assume lastRow were 100 then this would set a range from A1 to A10100: is that what you want? Or may be you'd use
.Range("A1:A" & lastRow)
again .Range("A19" & aCell.Row) would lead to a single cell address such as "A1989" (were aCell.Row = 89): is that what you want?
other than what above I can't grasp the actual scenario of what you're searching where. You may want to provide more info about that

Capture cell value with TextBox in UserForm

I have a UserForm which should be able to copy paste cells ideally. So firstly I would click the range I would want to copy, then activate the UserForm. The UserForm would have a combo box to choose which sheet I want to paste the data in, thereafter it would go to that sheet and user will click on the range or cell where he wants the data to be pasted.
I originally did an input box code to do this and it works perfectly, however when I do it in the UserForm it does not work as I am not able to incorporate the Type:=8 code in the textbox. Hence I would need some help on how can I enable my UserForm to paste cell data on the sheet, similarly to what I have done in application.inputbox.
This is the perfectly working code in the form of an input box:
Sub CopyPasteCumUpdateWithinSameSheet()
Dim rng As Range
Dim inp As Range
Selection.Interior.ColorIndex = 37
Set inp = Selection
On Error Resume Next
Set rng = Application.InputBox("Copy to", Type:=8)
On Error GoTo 0
If TypeName(rng) <> "Range" Then
Exit Sub
Else
inp.Copy
rng.Select
ActiveSheet.Paste Link:=True
'Cells(1,2).Font.ThemeColor =
End If
End Sub
This is the UserForm I have tried:
Dim Sh As Worksheet
Private Sub CommandButton1_Click()
On Error GoTo 0
If TypeName(rng) <> "Range" Then
Exit Sub
Else
inp.Copy
rng.Select
ActiveSheet.Paste Link:=True
End If
End Sub
Private Sub UserForm_Initialize()
CopyPasteUserform.Show vbModeless
For Each Sh In ThisWorkbook.Sheets
If Sh.Name <> "Inputs" Then
ComboBox1.AddItem Sh.Name
End If
Next
ComboBox1.Style = fmStyleDropDownList
End Sub
Private Sub ComboBox1_Change()
With ThisWorkbook.Sheets(ComboBox1.Text)
.Visible = xlSheetVisible
.Activate
End With
End Sub
Private Sub TextBox1_Change()
Dim rng As Range
Dim inp As Range
Selection.Interior.ColorIndex = 37
Set inp = Selection
On Error Resume Next
Set rng = TextBox.Value
End Sub
I tried incorporating the UserForm but all other functions stop responding apart from the RefEdit.
Dim Sh As Worksheet
Private Sub UserForm_Initialize()
CopyPasteUserform.Show vbModeless
For Each Sh In ThisWorkbook.Sheets
If Sh.Name <> "Inputs" Then
ComboBox1.AddItem Sh.Name
End If
Next
ComboBox1.Style = fmStyleDropDownList
Dim rng As Range
Dim inp As Range
Selection.Interior.ColorIndex = 37
Set inp = Selection
End Sub
Private Sub Combobox1_Change()
With ThisWorkbook.Sheets(ComboBox1.Text)
.Visible = xlSheetVisible
.Activate
End With
End Sub
Private Sub RefEdit1_Change()
Label1.Caption = ""
If RefEdit1.Value <> "" Then _
Label1.Caption = "[" & ComboBox1 & "]" & RefEdit1
Dim rng As Range
Dim inp As Range
On Error Resume Next
Set rng = RefEdit1.Value
On Error GoTo 0
If TypeName(rng) <> "Range" Then
Exit Sub
Else
inp.Copy
rng.Select
ActiveSheet.Paste Link:=True
End If
End Sub
You do not need the combobox to navigate to the sheets. That is the beauty of the Refedit
Is this what you are trying? I have not done any error handling. I am sure you can take care of that.
Create a userform and place 2 labels, 2 refedits and 1 commandbutton as shown below
Next paste this code in the userform code area
Code
Private Sub CommandButton1_Click()
Dim rngCopy As Range, rngPaste As Range
Dim wsCopy As Worksheet, wsPaste As Worksheet
If RefEdit1.Value <> "" And RefEdit2.Value <> "" Then
Set wsCopy = ThisWorkbook.Sheets(Replace(Split(RefEdit1.Value, "!")(0), "'", ""))
Set rngCopy = wsCopy.Range(Split(RefEdit1.Value, "!")(1))
Set wsPaste = ThisWorkbook.Sheets(Replace(Split(RefEdit2.Value, "!")(0), "'", ""))
Set rngPaste = wsPaste.Range(Split(RefEdit2.Value, "!")(1))
rngCopy.Copy rngPaste
Else
MsgBox "Please select Input and Output range"
End If
End Sub
In Action
The data will be copied from Sheet1!$A$1:$A$3 to Sheet2!$A$1:$A$3
Followup From Comments
However the pastelink feature has been missed out in the userform. Is it possible to incorporate it?:) – Niva 7 mins ago
Add a checkbox to the form as shown below
Use this code
Private Sub CommandButton1_Click()
Dim rngCopy As Range, rngPaste As Range
Dim wsCopy As Worksheet, wsPaste As Worksheet
If RefEdit1.Value <> "" And RefEdit2.Value <> "" Then
Set wsCopy = ThisWorkbook.Sheets(Replace(Split(RefEdit1.Value, "!")(0), "'", ""))
Set rngCopy = wsCopy.Range(Split(RefEdit1.Value, "!")(1))
Set wsPaste = ThisWorkbook.Sheets(Replace(Split(RefEdit2.Value, "!")(0), "'", ""))
Set rngPaste = wsPaste.Range(Split(RefEdit2.Value, "!")(1))
If CheckBox1.Value = True Then
wsPaste.Activate
rngPaste.Select
rngCopy.Copy
ActiveSheet.Paste Link:=True
Else
rngCopy.Copy rngPaste
End If
Else
MsgBox "Please select Input and Output range"
End If
End Sub
Description: Type:=8 will check that user input correct range name or not? In UserForm the TextBox not have this function. But we can detect this error when user click button. see my code.
No need to check when textbox is change, I delete code of textbox_change.
Replace below in your user form code area.
Option Explicit
Dim Sh As Worksheet
Dim inp As Range
Dim rng As Range
Private Sub CommandButton1_Click()
ActiveCell.Value = Me.TextBox1.Text
'On Error Resume Next
'If TypeName(Range(Me.TextBox1.Text)) <> "Range" Then
' MsgBox "Invalid range name!", vbCritical
' Exit Sub
'Else
' inp.Copy
' rng.Select
'
' ActiveSheet.Paste Link:=True
' MsgBox "Copy and paste finish.", vbInformation
'End If
'On Error GoTo 0
End Sub
Private Sub UserForm_Initialize()
For Each Sh In ThisWorkbook.Sheets
If Sh.Name <> "Inputs" Then
ComboBox1.AddItem Sh.Name
End If
Next
ComboBox1.Style = fmStyleDropDownList
End Sub
Private Sub ComboBox1_Change()
With ThisWorkbook.Sheets(ComboBox1.Text)
.Visible = xlSheetVisible
.Activate
End With
End Sub

Create new sheets based on a list

When I create new sheets based on the below VBA Code, it works as I want, but there is a small problem. The issue is that when creating all the sheets based on the list given in Column ("A"), it create one more sheet with the same name of the original one and also show an error in the code in this section
ActiveSheet.Name = c.Value
Any assistant to correct.
Private Sub CommandButton1_Click()
On Error Resume Next
Application.EnableEvents = False
Dim bottomA As Integer
bottomA = Range("A" & Rows.Count).End(xlUp).Row
Dim c As Range
Dim ws As Worksheet
For Each c In Range("A2:A" & bottomA)
Set ws = Nothing
On Error Resume Next
Set ws = Worksheets(c.Value)
On Error GoTo 0
If ws Is Nothing Then
Sheets("Format").Select
Sheets("Format").Copy After:=Sheets(Sheets.Count)
ActiveSheet.Name = c.Value
End If
Next
Application.EnableEvents = True
End Sub
I think you forgot in your For statement to state which worksheet the range will be on. So that line should be something like this:
For Each c in worksheet(1).Range("A2:A" & bottomA)
Also there other issue in your code, I just made quick re-write..
Private Sub CommandButton1_Click()
Dim c As Range
Dim ws As Worksheet
Dim bottomA As Integer
On Error GoTo eh
Application.EnableEvents = False
bottomA = Range("A" & Rows.Count).End(xlUp).Row
For Each c In Worksheets(1).Range("A2:A" & bottomA)
'Set ws = Nothing
'On Error Resume Next
'Set ws = Worksheets(c.Value)
'On Error GoTo 0
'If ws Is Nothing Then
Sheets("Format").Select
Sheets("Format").Copy After:=Sheets(Sheets.Count)
ActiveSheet.Name = c.Value
'End If
Next
Application.EnableEvents = True
Exit Sub
eh:
Debug.Print ""
Debug.Print Err.Description
MsgBox (Err.Description)
End Sub
Try to be explicit as much as possible.
Private Sub CommandButton1_Click()
On Error GoTo halt ' Do not use OERN, that ignores the error
Application.EnableEvents = False
Dim bottomA As Long
' explicitly work on the target sheet
With Sheets("SheetName")
bottomA = .Range("A" & .Rows.Count).End(xlUp).Row
Dim c As Range, ws As Worksheet, wb As Workbook
' explicitly define which workbook your working on
Set wb = ThisWorkbook
For Each c In .Range("A2:A" & bottomA)
On Error Resume Next
Set ws = wb.Sheets(c.Value)
On Error GoTo 0
If ws Is Nothing Then
wb.Sheets("Sheet1").Copy _
After:=wb.Sheets(wb.Sheets.Count)
ActiveSheet.Name = c.Value
End If
Next
End With
forward:
Application.EnableEvents = True
Exit Sub
halt:
MsgBox Err.Number
Resume forward
End Sub
I don't know why you need to turn events On/Off (I don't see it required at least for your example). Nonetheless, I replaced the On Error Resume Next with a more flexible error handling routine because what you did is simply ignoring any errors. Check this out as well to improve how you work with objects and avoid unnecessary use of Active[object] and Select.