0

Excel starts with two sheets.
First a list which includes data for a name, a number, and a product numbers.
The second tab is a template.

I'm trying to:
Copy the template tab, input the name, number, and product into the new tab, and then rename the tab (ActiveSheet.Name = Range("B3").Value).
Loop down to the next row and repeat until there are no more rows.
If a tab already exists with the name, then move onto the next row.

I tried two methods.

The code below I could probably figure out but it would require me to copy and paste the same lines with updated rows about 100 times since it isn't looping.
Also, the macro stops if there's already a tab with the name on it instead of continuing.

I made several attempts to have the macro move on if a tab has already been created from a name on the list but this keeps breaking the macro.

Sub TemplateMultiple()
'
' Tab creation and naming
'

'
    Sheets("Template").Select
    Sheets("Template").Copy Before:=Sheets(2)
    Range("B3:C3").Select
    ActiveCell.FormulaR1C1 = "='List'!R[2]C"
    Range("B5:C5").Select
    ActiveCell.FormulaR1C1 = "='List'!RC[3]"
    Range("B6:C6").Select
    ActiveCell.FormulaR1C1 = "='List'!R[-1]C[4]"
    Range("B7:C7").Select
    ActiveSheet.Name = Range("B3").Value
    
    Sheets("Template").Select
    Sheets("Template").Copy Before:=Sheets(3)
    Range("B3:C3").Select
    ActiveCell.FormulaR1C1 = "='List'!R[3]C"
    Range("B5:C5").Select
    ActiveCell.FormulaR1C1 = "='List'!R[2]C[3]"
    Range("B6:C6").Select
    ActiveCell.FormulaR1C1 = "='List'!R[0]C[4]"
    Range("B7:C7").Select
    ActiveSheet.Name = Range("B3").Value
    
    Sheets("Template").Select
    Sheets("Template").Copy Before:=Sheets(4)
    Range("B3:C3").Select
    ActiveCell.FormulaR1C1 = "='List'!R[4]C"
    Range("B5:C5").Select
    ActiveCell.FormulaR1C1 = "='List'!R[2]C[3]"
    Range("B6:C6").Select
    ActiveCell.FormulaR1C1 = "='List'!R[1]C[4]"
    Range("B7:C7").Select
    ActiveSheet.Name = Range("B3").Value
    
    Sheets("Template").Select
    Sheets("Template").Copy Before:=Sheets(5)
    Range("B3:C3").Select
    ActiveCell.FormulaR1C1 = "='List'!R[5]C"
    Range("B5:C5").Select
    ActiveCell.FormulaR1C1 = "='List'!R[3]C[3]"
    Range("B6:C6").Select
    ActiveCell.FormulaR1C1 = "='List'!R[2]C[4]"
    Range("B7:C7").Select
    ActiveSheet.Name = Range("B3").Value
    
    Sheets("Template").Select
    Sheets("Template").Copy Before:=Sheets(6)
    Range("B3:C3").Select
    ActiveCell.FormulaR1C1 = "='List'!R[6]C"
    Range("B5:C5").Select
    ActiveCell.FormulaR1C1 = "='List'!R[4]C[3]"
    Range("B6:C6").Select
    ActiveCell.FormulaR1C1 = "='List'!R[3]C[4]"
    Range("B7:C7").Select
    ActiveSheet.Name = Range("B3").Value
End Sub

The second method involves a loop to make the code much easier to read/follow.
My code is putting the same information into each template instead of going down one row for each spreadsheet.

Sub Template1()
'UpdatebyExtendoffice20161222
    Dim x As Integer
    Application.ScreenUpdating = False
    ' Set numrows = number of rows of data.
    NumRows = Range("B5", Range("B5").End(xlDown)).Rows.Count
    ' Select cell a1.
    Range("B5").Select
    ' Establish "For" loop to loop "numrows" number of times.
    For x = 1 To NumRows
        ' Insert your code here.
        Sheets("Template").Select
        Sheets("Template").Copy Before:=Sheets(2)
        Range("B3:C3").Select
        ActiveCell.FormulaR1C1 = "='List'!R[2]C"
        Range("B5:C5").Select
        ActiveCell.FormulaR1C1 = "='List'!RC[3]"
        Range("B6:C6").Select
        ActiveCell.FormulaR1C1 = "='List'!R[-1]C[4]"
        Range("B7:C7").Select
        ActiveSheet.Name = Range("B3").Value
        ' Selects cell down 1 row from active cell.
        ActiveCell.Offset(1, 0).Select
    Next
    Application.ScreenUpdating = True
End Sub
Community
  • 1
  • 1
Bobby
  • 1

1 Answers1

1

Something like this should work:

Sub Template1()

    Dim wb As Workbook, ws As Worksheet, wsList As Worksheet
    Dim c As Range, sheetName As String, wsTempl As Worksheet
    
    Set wb = ThisWorkbook
    Set wsList = wb.Worksheets("List")
    Set wsTempl = wb.Worksheets("Template")
    
    Application.ScreenUpdating = False
    
    For Each c In wsList.Range("B5", wsList.Cells(Rows.Count, "B").End(xlUp)).Cells
        sheetName = c.Value
        Set ws = GetWorksheet(wb, sheetName) 'see if there's an existing sheet with this name
        If ws Is Nothing Then                'if was no matching sheet
            wsTempl.Copy before:=wsTempl     'copy template in front of itself
            Set ws = wb.Worksheets(wsTempl.Index - 1) 'get a reference to the copy
            ws.Name = sheetName
            With c.EntireRow
                'I never use R1C1 so this might be off...
                ws.Range("B3:C3").Formula = "='List'!" & .Columns("B").Address(False, False)
                ws.Range("B5:C5").Formula = "='List'!" & .Columns("E").Address(False, False)
                ws.Range("B6:C6").Formula = "='List'!" & .Columns("E").Address(False, False)
            End With
        End If
    Next c
    
    Application.ScreenUpdating = True
End Sub

'Return a worksheet named `wsName` from workbook `wb`, or `Nothing` if it doesn't exist
Function GetWorksheet(wb As Workbook, wsName As String) As Worksheet
    On Error Resume Next
    Set GetWorksheet = wb.Worksheets(wsName)
    On Error Goto 0
End Function

Note there's rarely any need to select/activate things before you work with them - that's an artifact of the macro recorder. See How to avoid using Select in Excel VBA for more on this and some good guidelines to follow.

Tim Williams
  • 154,628
  • 8
  • 97
  • 125
  • Wow, this is awesome. Thanks so much for your help! I'll check out that link and I also learned something new. I couldn't quite understand the R1C1 (it came from macro recorder), so I'll definitely start using your method as the cell ranges seem much easier. – Bobby Jul 14 '22 at 21:27
  • @TimWilliams What's the benefit of a further `On Error Resume Next` in the `GetWorksheet` function? – T.M. Jul 16 '22 at 18:11
  • 1
    @T.M. - typo - should have been `On Error Goto 0` Fixed above, thanks. – Tim Williams Jul 16 '22 at 21:23