Creating sheets from rows on a "Master Roster" sheet with each new sheet being a copy of a template

juscuz419

Board Regular
Joined
Apr 18, 2023
Messages
57
Office Version
  1. 2019
Platform
  1. Windows
I have a workbook that has a Master Roster Sheet and a Template sheet among others. The Master Roster sheet can and does change frequently from event to event. The Template sheet has cells that are populated from the Master Roster Sheet. I currently manually create a new copy of the template sheet for each row that is not blank within a range on the Master Roster sheet and then go to each sheet and repair the cell reference back to the Master Roster row for that individual sheet.
What I would like to build is a macro button that can be selected to run when the Master Roster range is complete for each event that creates a new sheet that is a copy of the template sheet with the cell references on each sheet accurately pointing back to specific information for a row in the Master Roster sheet
 

Excel Facts

Select a hidden cell
Somehide hide payroll data in column G? Press F5. Type G1. Enter. Look in formula bar while you arrow down through G.
This seems pretty doable. Ideally you post a link to the workbook so a potential helper does not have to create code in the abstract. Use the link icon above. Use Box, Dropbox or 1drive.
 
Upvote 0
Thank you for the response. I had to remove some information from the workbook that may have been personal or proprietary so I created a stripped down version. I do not see a link Icon that you mentioned. Could you clarify or point me to it, please?
 
Upvote 0
The link icon is at the top of the message area.
 

Attachments

  • LinkIcon.png
    LinkIcon.png
    1.3 KB · Views: 11
Upvote 0
The linked workbook is a stripped down version of what I use. The sequence of use is I Delete the sheets from the previous event then I complete a roster for the new event in the Master Roster sheet. I then create a copy of the Template Sheet for each non blank row at the top (row 5 through 26) section of the Master Roster sheet and name the sheet with the Initials in column A (A5:A26). I then go to each individual sheet and "correct" the cell reference back to the Master Roster sheet for 12 cells that I have highlighted in the Template sheet.
It would be great if there were a way to have two user selectable buttons to 1) select and delete the old sheets and 2) Create, name, and correct the cell references for each member of the roster.Timesheet
 
Upvote 0
Is it NECESSARY to use CELL REFERENCES to "point" to the respective data item in the template sheet for each person? Instead I propose that the macro put the VALUE into the respective cell in the template sheet. No cell references are needed.

Have a look at this web page and this web page that characterize range names in Excel. I propose using such range names instead of cell addresses. Cleaner. Less error-prone.
 
Upvote 0
Would each of the twelve cells need to be named? How would each row from the roster be tied to the correct sheet created from the template?
 
Upvote 0
Yes, all twelve single celled range names exist in the template worksheet.

Furthermore, so code knows where to go to get the various data values to transfer into the copy of the template workbook, I added twelve names in the Master Roster, one each for the column HEADERs from which data is transferred. For example, the column header for first name is named Header_FirstName. Also the column header for initials is named Header_Initial.

One small complicating factor is "Sheet-scoped" names. That is, you can define a name whose "scope" 1) is the entire workbook OR 2) a specific to a worksheet. All names I added are worksheet scoped names.

I also used "code names" for the workbooks. That is good for at least one reason: if the sheet name/tab changes the code still refers to the correct worksheet. I'm sure that that sounds complicated but once you get the hang of it it is easy and a good way to do programming when referring to worksheets. In code a worksheet is referred to like this [Template] where the code name is Template.

See HERE for articles about code names.

All that said, the workbook that I put together -- based on what you provided -- is HERE.

Let me know if it does what is needed.

VBA Code:
Option Explicit


Sub DeleteExistingSheets()

    Dim wsCurrentSheet As Worksheet
    
    Dim sRangeRefersTo As String
    
    For Each wsCurrentSheet In ThisWorkbook.Worksheets
        
'       Look for the name IsTemplate in the sheet to determine if it is one to delete.
'       The Template sheet and copies thereof have a name whose RefersTo = "=TRUE".

'       If the sheet being processed is the Template sheet or a copy thereof Then
'       the right four characters of the RefersTo for the name IsTemplate = "TRUE".

        sRangeRefersTo = ""
        
        On Error Resume Next
        sRangeRefersTo = Right(wsCurrentSheet.Names("IsTemplate").RefersTo, 4)
        On Error GoTo 0
        
'       If the sheet is a COPY of the Template worksheet then delete it.
        If sRangeRefersTo = "TRUE" And wsCurrentSheet.CodeName <> "Template" _
         Then
         
'           Don't ask user if it is ok to delete a worksheet.
            Application.DisplayAlerts = False
            
'           Delete the worksheet.
            wsCurrentSheet.Delete
         
        End If
    
    Next

End Sub

VBA Code:
Option Explicit

Sub CreateSheets()

'   Worksheet object will point to the worksheet being processed.
    Dim wsNewSheet As Worksheet
    
'   Count of occupied rows in the Master Roster worksheet.
    Dim iOccupiedRows As Long
    
'   Used to iterate/loop through names found.
    Dim iRow As Long
    
'   Get count of all worksheets in the workbook.
    Dim iExistingSheetsCount As Long
    
'   This variable holds the initials for a person being processed.
    Dim sInitials As String

'   Determine how many rows in the Master Roster worksheet contain names.
'   Look in the column for initials. The header cell in that column is
'   named "Header_Initials".
    With [MasterRoster].Range("Header_Initials").Offset(1)
    
        Do While .Cells(iOccupiedRows).Offset(1) <> ""
           iOccupiedRows = iOccupiedRows + 1
        Loop

    End With
    
'   If there are rows with data in them in the Master Roster then process the names.
    If iOccupiedRows > 0 _
     Then
     
'       Delete all copies of the Template worksheet. Calls sub named DeleteExistingSheets.
        Call DeleteExistingSheets
        
        iExistingSheetsCount = ThisWorkbook.Worksheets.Count

'       Iterate/loop through all rows containing data needed to populate a copy of
'       the template worksheet.
        For iRow = 1 To iOccupiedRows
            
'           Get initials for the row/copy of template being processed.
            sInitials = [MasterRoster].Range("Header_Initials").Offset(iRow).Value
            
'           Make copy of the template sheet. Place it after the most recently
'           added copy of the template worksheet. USed code name to refer to the
'           template worksheet. It is now the ActiveSheet.
            [Template].Copy After:=Sheets(iExistingSheetsCount - 1)
    
'           Keep track of how many copies of the template worksheet have been made.
            iExistingSheetsCount = iExistingSheetsCount + 1
        
'           Put data into the newly created copy of the template sheet. It is the ActiveSheet.
            With ActiveSheet
    
'               Name the newly created copy of the template sheet based on initials.
                .Name = sInitials
    
'               Copy data for the current row into the newly created copy of the template worksheet.
                .Range("FirstName").Value = [MasterRoster].Range("Header_FirstName").Offset(iRow).Value
    
                .Range("LastName").Value = [MasterRoster].Range("Header_LastName").Offset(iRow).Value
    
                .Range("MiddleName").Value = [MasterRoster].Range("Header_MiddleName").Offset(iRow).Value
    
                .Range("Address").Value = [MasterRoster].Range("Header_Address").Offset(iRow).Value
    
                .Range("City").Value = [MasterRoster].Range("Header_City").Offset(iRow).Value
    
                .Range("State").Value = [MasterRoster].Range("Header_State").Offset(iRow).Value
    
                .Range("ZipCode").Value = [MasterRoster].Range("Header_ZipCode").Offset(iRow).Value
    
                .Range("PhoneNumber").Value = [MasterRoster].Range("Header_PhoneNumber").Offset(iRow).Value
    
                .Range("EmailAddress").Value = [MasterRoster].Range("Header_EmailAddress").Offset(iRow).Value
    
                .Range("Position").Value = [MasterRoster].Range("Header_Position").Offset(iRow).Value
    
                .Range("TeamNumber").Value = [MasterRoster].Range("Header_TeamNumber").Offset(iRow).Value
    
                .Range("TagNumber").Value = [MasterRoster].Range("Header_TagNumber").Offset(iRow).Value
    
            End With
        
        Next iRow
    
    End If

End Sub
 
Upvote 0
I just thought of a minor issue. The approach that I use to determine how many names there are to process in the Master Roster worksheet looks for the first empty cell in the first name column (column C). If there are 26 names then my code will try to make 27 or more copies of the template because row 27 contains the header *FirstName (i.e., is not empty).

The easy way to fix that is to insert an empty row above row 27 and not use that row for a person. Make sure that cell C27 is empty and stays empty. I suggest clearing any formatting so it is obvious that row 27 is empty and is BETWEEN the names and the headers now in row 27. I hope that that is not too convoluted.
 
Upvote 0
Another issue cropped up. Code will choke if you forgot to input initials for a person. This code catches that.

VBA Code:
Sub CreateSheets()

'   Worksheet object will point to the worksheet being processed.
    Dim wsNewSheet As Worksheet
    
'   Count of occupied rows in the Master Roster worksheet.
    Dim iOccupiedRows As Long
    
'   Used to iterate/loop through names found.
    Dim iRow As Long
    
'   Get count of all workshets in the workbook.
    Dim iExistingSheetsCount As Long
    
'   This variable holds the initials for a person being processed.
    Dim sInitials As String

'   Determine how many rows in the Master Roster worksheet contain names.
'   Look in the column for initials. The header cell in that column is
'   named "Header_Initials".
    With [MasterRoster].Range("Header_Initials").Offset(1)
    
        Do While .Cells(iOccupiedRows).Offset(1) <> ""
           iOccupiedRows = iOccupiedRows + 1
        Loop

    End With
    
'   If there are rows with data in them in the Master Roster then process the names.
    If iOccupiedRows > 0 _
     Then
     
'       Delete all copies of the Template worksheet. Calls sub named DeleteExistingSheets.
        Call DeleteExistingSheets
        
        iExistingSheetsCount = ThisWorkbook.Worksheets.Count

'       Iterate/loop through all rows containing data needed to populate a copy of
'       the template worksheet.
        For iRow = 1 To iOccupiedRows
            
'           Get initials for the row/copy of template being processed.
            sInitials = [MasterRoster].Range("Header_Initials").Offset(iRow).Value
            
'           Do not try to create a sheet with no initials.
            If sInitials <> "" _
             Then
            
'               Make copy of the template sheet. Place it after the most recently
'               added copy of the template worksheet. Used code name to refer to the
'               template worksheet. It is now the ActiveSheet.
                [Template].Copy After:=Sheets(iExistingSheetsCount - 1)
        
'               Keep track of how many copies of the template worksheet have been made.
                iExistingSheetsCount = iExistingSheetsCount + 1
            
'               Put data into the newly created copy of the template sheet. It is the ActiveSheet.
                With ActiveSheet
        
'                   Name the newly created copy of the template sheet based on initials.
                    .Name = sInitials
        
'                   Copy data for the current row into the newly created copy of the template worksheet.
                    .Range("FirstName").Value = [MasterRoster].Range("Header_FirstName").Offset(iRow).Value
        
                    .Range("LastName").Value = [MasterRoster].Range("Header_LastName").Offset(iRow).Value
        
                    .Range("MiddleName").Value = [MasterRoster].Range("Header_MiddleName").Offset(iRow).Value
        
                    .Range("Address").Value = [MasterRoster].Range("Header_Address").Offset(iRow).Value
        
                    .Range("City").Value = [MasterRoster].Range("Header_City").Offset(iRow).Value
        
                    .Range("State").Value = [MasterRoster].Range("Header_State").Offset(iRow).Value
        
                    .Range("ZipCode").Value = [MasterRoster].Range("Header_ZipCode").Offset(iRow).Value
        
                    .Range("PhoneNumber").Value = [MasterRoster].Range("Header_PhoneNumber").Offset(iRow).Value
        
                    .Range("EmailAddress").Value = [MasterRoster].Range("Header_EmailAddress").Offset(iRow).Value
        
                    .Range("Position").Value = [MasterRoster].Range("Header_Position").Offset(iRow).Value
        
                    .Range("TeamNumber").Value = [MasterRoster].Range("Header_TeamNumber").Offset(iRow).Value
        
                    .Range("TagNumber").Value = [MasterRoster].Range("Header_TagNumber").Offset(iRow).Value
        
                End With
            
            End If
        
        Next iRow
    
    End If

End Sub
 
Upvote 0

Forum statistics

Threads
1,214,932
Messages
6,122,332
Members
449,077
Latest member
jmsotelo

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top