VBA copy cells based on text string

collirde

New Member
Joined
Mar 13, 2016
Messages
8
Hello and I hope I can find a little help. I know just enough VBA to get myself running down rabbit holes trying to figure things out.

I have a sheet that I want to create another sheet from the info on it. I need to create a new sheet "SUBLIST" and for each teacher in Column B, I need to make a separate row for each block they will need a substitute (looking in column D "Time Out"). If they have a 1, then I need the info from Class1 and Room1 along with the substitute's name from column V. Then do the same for 2, Class2 and Room2 along with the name of the sub. Continue this for 3 and 4.

Any help would be appreciated as I am trying to help a co-worker out and simplify their daily routine.

Thanks in advance.

Ray



Starting Sheet:

1603814991899.png


What I am hoping to get in a new sheet:
1603818586278.png
 

Excel Facts

Round to nearest half hour?
Use =MROUND(A2,"0:30") to round to nearest half hour. Use =CEILING(A2,"0:30") to round to next half hour.
Okay Ray, how about ...

VBA Code:
Public Sub Collirde()

    Const cSourceSheet      As String = "Sheet1"     ' << Change sheet names as required
    Const cDestinationSheet As String = "SUBLIST"

    Dim oWsSrc  As Worksheet
    Dim oWsDest As Worksheet
    Dim rng     As Range
    Dim arrIN   As Variant
    Dim arrOUT  As Variant
    Dim r       As Long
    Dim n       As Long
    Dim lRow    As Long
    Dim iMax    As Integer
    Dim iBlock  As Integer

    ' unconditionally delete any pre-existing target worksheet
    For Each oWsDest In ThisWorkbook.Sheets
        If StrComp(cDestinationSheet, oWsDest.Name, vbTextCompare) = 0 Then
            Application.DisplayAlerts = False
            oWsDest.Delete
            Application.DisplayAlerts = True
            Exit For
        End If
    Next

    ' provide a blank target worksheet
    With ThisWorkbook
        Set oWsDest = .Sheets.Add(after:=.Sheets(.Sheets.Count))
    End With
    oWsDest.Name = cDestinationSheet

    ' allocate memory for source data and perform copy
    Set oWsSrc = ThisWorkbook.Sheets(cSourceSheet)
    With oWsSrc
        arrIN = .Range("B3", .Cells(.Rows.Count, "B").End(xlUp)).Resize(, 13)
    End With

    ' read source data
    For r = 1 To UBound(arrIN, 1)
        iMax = Len(arrIN(r, 3))
        ' allocate memory for destination data
        ReDim arrOUT(1 To iMax, 1 To 5)
        ' rearrange destination data
        For n = 1 To iMax
            iBlock = Mid(arrIN(r, 3), n, 1)
            arrOUT(n, 1) = arrIN(r, 1)
            arrOUT(n, 2) = iBlock
            arrOUT(n, 5) = arrIN(r, 13)
            Select Case iBlock
                Case 1
                    arrOUT(n, 3) = arrIN(r, 5)
                    arrOUT(n, 4) = arrIN(r, 6)
                Case 2
                    arrOUT(n, 3) = arrIN(r, 7)
                    arrOUT(n, 4) = arrIN(r, 8)
                Case 3
                    arrOUT(n, 3) = arrIN(r, 9)
                    arrOUT(n, 4) = arrIN(r, 10)
                Case 4
                    arrOUT(n, 3) = arrIN(r, 11)
                    arrOUT(n, 4) = arrIN(r, 12)
            End Select
        Next n
        
        ' determine destination area on sheet and paste rearranged data
        Set rng = oWsDest.Range("A" & 3 + lRow).Resize(iMax, 5)
        rng = arrOUT
        lRow = lRow + iMax
    Next r

    ' finally create some headers
    With oWsDest.Range("A2:E2")
        .Font.Bold = True
        .EntireColumn.HorizontalAlignment = xlCenter
        .Cells(, 1).EntireColumn.HorizontalAlignment = xlGeneral
        .Cells(, 1) = "Teacher Name"
        .Cells(, 2) = "Block"
        .Cells(, 3) = "Class"
        .Cells(, 4) = "Room"
        .Cells(, 5) = "Sub's Name"
    End With
    rng.EntireColumn.AutoFit
End Sub
 
Upvote 0
Okay Ray, how about ...

VBA Code:
Public Sub Collirde()

    Const cSourceSheet      As String = "Sheet1"     ' << Change sheet names as required
    Const cDestinationSheet As String = "SUBLIST"

    Dim oWsSrc  As Worksheet
    Dim oWsDest As Worksheet
    Dim rng     As Range
    Dim arrIN   As Variant
    Dim arrOUT  As Variant
    Dim r       As Long
    Dim n       As Long
    Dim lRow    As Long
    Dim iMax    As Integer
    Dim iBlock  As Integer

    ' unconditionally delete any pre-existing target worksheet
    For Each oWsDest In ThisWorkbook.Sheets
        If StrComp(cDestinationSheet, oWsDest.Name, vbTextCompare) = 0 Then
            Application.DisplayAlerts = False
            oWsDest.Delete
            Application.DisplayAlerts = True
            Exit For
        End If
    Next

    ' provide a blank target worksheet
    With ThisWorkbook
        Set oWsDest = .Sheets.Add(after:=.Sheets(.Sheets.Count))
    End With
    oWsDest.Name = cDestinationSheet

    ' allocate memory for source data and perform copy
    Set oWsSrc = ThisWorkbook.Sheets(cSourceSheet)
    With oWsSrc
        arrIN = .Range("B3", .Cells(.Rows.Count, "B").End(xlUp)).Resize(, 13)
    End With

    ' read source data
    For r = 1 To UBound(arrIN, 1)
        iMax = Len(arrIN(r, 3))
        ' allocate memory for destination data
        ReDim arrOUT(1 To iMax, 1 To 5)
        ' rearrange destination data
        For n = 1 To iMax
            iBlock = Mid(arrIN(r, 3), n, 1)
            arrOUT(n, 1) = arrIN(r, 1)
            arrOUT(n, 2) = iBlock
            arrOUT(n, 5) = arrIN(r, 13)
            Select Case iBlock
                Case 1
                    arrOUT(n, 3) = arrIN(r, 5)
                    arrOUT(n, 4) = arrIN(r, 6)
                Case 2
                    arrOUT(n, 3) = arrIN(r, 7)
                    arrOUT(n, 4) = arrIN(r, 8)
                Case 3
                    arrOUT(n, 3) = arrIN(r, 9)
                    arrOUT(n, 4) = arrIN(r, 10)
                Case 4
                    arrOUT(n, 3) = arrIN(r, 11)
                    arrOUT(n, 4) = arrIN(r, 12)
            End Select
        Next n
       
        ' determine destination area on sheet and paste rearranged data
        Set rng = oWsDest.Range("A" & 3 + lRow).Resize(iMax, 5)
        rng = arrOUT
        lRow = lRow + iMax
    Next r

    ' finally create some headers
    With oWsDest.Range("A2:E2")
        .Font.Bold = True
        .EntireColumn.HorizontalAlignment = xlCenter
        .Cells(, 1).EntireColumn.HorizontalAlignment = xlGeneral
        .Cells(, 1) = "Teacher Name"
        .Cells(, 2) = "Block"
        .Cells(, 3) = "Class"
        .Cells(, 4) = "Room"
        .Cells(, 5) = "Sub's Name"
    End With
    rng.EntireColumn.AutoFit
End Sub
This is awesome, but there are some small bugs that I can't figure out, plus I need to see if you can make an adjustment based on a change the person wanted in the output. I am attaching pics of a sample source data (slightly changed) and what I am currently getting along with what I would like to have. I really appreciate your help.

Source Data:
1603977005800.png


Current Output:
1603976316527.png


Desired Output:(with additional info)
1603977436351.png
 

Attachments

  • 1603975837327.png
    1603975837327.png
    54.5 KB · Views: 7
Upvote 0
This is awesome, but there are some small bugs
... no bugs (although I missed the hidden columns in the image of your post #1 ? )
In case you're getting errors running the code let me know.
Meanwhile let me look into it ...
 
Upvote 0
... no bugs (although I missed the hidden columns in the image of your post #1 ? )
In case you're getting errors running the code let me know.
Meanwhile let me look into it ...
You were awesome, no "bugs" just my fault for having hidden columns. I really appreciate the help.
 
Upvote 0
You are welcome. See if this works for you...

VBA Code:
Public Sub Collirde_r2()

    Const cSourceSheet      As String = "Sheet1"     ' << Change sheet names as required
    Const cDestinationSheet As String = "SUBLIST2"

    Dim oWsSrc  As Worksheet
    Dim oWsDest As Worksheet
    Dim rng     As Range
    Dim arrIN   As Variant
    Dim arrOUT  As Variant
    Dim r       As Long
    Dim n       As Long
    Dim lRow    As Long
    Dim iMax    As Integer
    Dim iBlock  As Integer

    ' unconditionally delete any pre-existing target worksheet
    For Each oWsDest In ThisWorkbook.Sheets
        If StrComp(cDestinationSheet, oWsDest.Name, vbTextCompare) = 0 Then
            Application.DisplayAlerts = False
            oWsDest.Delete
            Application.DisplayAlerts = True
            Exit For
        End If
    Next

    ' provide a blank target worksheet
    With ThisWorkbook
        Set oWsDest = .Sheets.Add(after:=.Sheets(.Sheets.Count))
    End With
    oWsDest.Name = cDestinationSheet

    ' allocate memory for source data and perform copy
    Set oWsSrc = ThisWorkbook.Sheets(cSourceSheet)
    With oWsSrc
        arrIN = .Range("B3", .Cells(.Rows.Count, "B").End(xlUp)).Resize(, 22)
    End With

    ' read source data
    For r = 1 To UBound(arrIN, 1)
        iMax = Len(arrIN(r, 3))
        ' allocate memory for destination data
        ReDim arrOUT(1 To iMax, 1 To 6)
        ' rearrange destination data
        For n = 1 To iMax
            iBlock = Mid(arrIN(r, 3), n, 1)
            arrOUT(n, 1) = arrIN(r, 1)
            arrOUT(n, 2) = iBlock
            arrOUT(n, 5) = arrIN(r, 21)
            arrOUT(n, 6) = arrIN(r, 22)
            Select Case iBlock
                Case 1
                    arrOUT(n, 3) = arrIN(r, 6)
                    arrOUT(n, 4) = arrIN(r, 7)
                Case 2
                    arrOUT(n, 3) = arrIN(r, 9)
                    arrOUT(n, 4) = arrIN(r, 10)
                Case 3
                    arrOUT(n, 3) = arrIN(r, 12)
                    arrOUT(n, 4) = arrIN(r, 13)
                Case 4
                    arrOUT(n, 3) = arrIN(r, 15)
                    arrOUT(n, 4) = arrIN(r, 16)
            End Select
        Next n
        
        ' determine destination area on sheet and paste rearranged data
        Set rng = oWsDest.Range("A" & 3 + lRow).Resize(iMax, 6)
        rng = arrOUT
        lRow = lRow + iMax
    Next r

    ' finally create some headers
    With oWsDest.Range("A2:F2")
        .Font.Bold = True
        .EntireColumn.HorizontalAlignment = xlCenter
        .Cells(, 1).EntireColumn.HorizontalAlignment = xlGeneral
        .Cells(, 1) = "Teacher Name"
        .Cells(, 2) = "Block"
        .Cells(, 3) = "Class"
        .Cells(, 4) = "Room"
        .Cells(, 5) = "Inc and TA"
        .Cells(, 6) = "Sub's Name"
    End With
    rng.EntireColumn.AutoFit
End Sub
 
Upvote 0
You are welcome. See if this works for you...

VBA Code:
Public Sub Collirde_r2()

    Const cSourceSheet      As String = "Sheet1"     ' << Change sheet names as required
    Const cDestinationSheet As String = "SUBLIST2"

    Dim oWsSrc  As Worksheet
    Dim oWsDest As Worksheet
    Dim rng     As Range
    Dim arrIN   As Variant
    Dim arrOUT  As Variant
    Dim r       As Long
    Dim n       As Long
    Dim lRow    As Long
    Dim iMax    As Integer
    Dim iBlock  As Integer

    ' unconditionally delete any pre-existing target worksheet
    For Each oWsDest In ThisWorkbook.Sheets
        If StrComp(cDestinationSheet, oWsDest.Name, vbTextCompare) = 0 Then
            Application.DisplayAlerts = False
            oWsDest.Delete
            Application.DisplayAlerts = True
            Exit For
        End If
    Next

    ' provide a blank target worksheet
    With ThisWorkbook
        Set oWsDest = .Sheets.Add(after:=.Sheets(.Sheets.Count))
    End With
    oWsDest.Name = cDestinationSheet

    ' allocate memory for source data and perform copy
    Set oWsSrc = ThisWorkbook.Sheets(cSourceSheet)
    With oWsSrc
        arrIN = .Range("B3", .Cells(.Rows.Count, "B").End(xlUp)).Resize(, 22)
    End With

    ' read source data
    For r = 1 To UBound(arrIN, 1)
        iMax = Len(arrIN(r, 3))
        ' allocate memory for destination data
        ReDim arrOUT(1 To iMax, 1 To 6)
        ' rearrange destination data
        For n = 1 To iMax
            iBlock = Mid(arrIN(r, 3), n, 1)
            arrOUT(n, 1) = arrIN(r, 1)
            arrOUT(n, 2) = iBlock
            arrOUT(n, 5) = arrIN(r, 21)
            arrOUT(n, 6) = arrIN(r, 22)
            Select Case iBlock
                Case 1
                    arrOUT(n, 3) = arrIN(r, 6)
                    arrOUT(n, 4) = arrIN(r, 7)
                Case 2
                    arrOUT(n, 3) = arrIN(r, 9)
                    arrOUT(n, 4) = arrIN(r, 10)
                Case 3
                    arrOUT(n, 3) = arrIN(r, 12)
                    arrOUT(n, 4) = arrIN(r, 13)
                Case 4
                    arrOUT(n, 3) = arrIN(r, 15)
                    arrOUT(n, 4) = arrIN(r, 16)
            End Select
        Next n
       
        ' determine destination area on sheet and paste rearranged data
        Set rng = oWsDest.Range("A" & 3 + lRow).Resize(iMax, 6)
        rng = arrOUT
        lRow = lRow + iMax
    Next r

    ' finally create some headers
    With oWsDest.Range("A2:F2")
        .Font.Bold = True
        .EntireColumn.HorizontalAlignment = xlCenter
        .Cells(, 1).EntireColumn.HorizontalAlignment = xlGeneral
        .Cells(, 1) = "Teacher Name"
        .Cells(, 2) = "Block"
        .Cells(, 3) = "Class"
        .Cells(, 4) = "Room"
        .Cells(, 5) = "Inc and TA"
        .Cells(, 6) = "Sub's Name"
    End With
    rng.EntireColumn.AutoFit
End Sub
This worked great. I just wish I could understand exactly what it is all doing, cause now they asked me to include "Lunch" in the output. I am trying to follow what you wrote to figure it out, but if it is not an issue for you, can you help me add that???? If not either I will figure it out or they will live without it.
 
Upvote 0
... cause now they asked me to include "Lunch" in the output. I am trying to follow what you wrote to figure it out, but if it is not an issue for you, can you help me add that????
No problem at all, but perhaps it would be better if I explain my code in more detail, so that you can make future changes to the output yourself. Do you agree with that?
 
Upvote 0
No problem at all, but perhaps it would be better if I explain my code in more detail, so that you can make future changes to the output yourself. Do you agree with that?
I would appreciate that, and I should be able to understand, but I don't want to burden you. You have already helped so much. But whatever you want to do (or not do) is fine with me.
 
Upvote 0
See if this meets your needs, if not let me know.

VBA Code:
Public Sub Collirde_r3()

    Const cSourceSheet      As String = "Sheet1"     ' << Change sheet names as required
    Const cDestinationSheet As String = "SUBLIST2"

    Dim oWsSrc  As Worksheet
    Dim oWsDest As Worksheet
    Dim rng     As Range
    Dim arrIN   As Variant
    Dim arrOUT  As Variant
    Dim r       As Long
    Dim n       As Long
    Dim lRow    As Long
    Dim iMax    As Integer
    Dim iBlock  As Integer

    ' unconditionally delete any pre-existing target worksheet
    For Each oWsDest In ThisWorkbook.Sheets
        If StrComp(cDestinationSheet, oWsDest.Name, vbTextCompare) = 0 Then
            Application.DisplayAlerts = False
            oWsDest.Delete
            Application.DisplayAlerts = True
            Exit For
        End If
    Next

    ' provide a blank target worksheet
    With ThisWorkbook
        Set oWsDest = .Sheets.Add(after:=.Sheets(.Sheets.Count))
    End With
    oWsDest.Name = cDestinationSheet

    ' allocate memory for source data and perform copy
    Set oWsSrc = ThisWorkbook.Sheets(cSourceSheet)
    With oWsSrc
        ' [] this part determines which area within column B has actually been used, starting from cell B3 and downwards
        ' [] since column B is just one column, Resize statement is used to extend the primary result with some adjacent
        '    columns at the right hand side, from 1 (col B) to 22 (col W)
        ' [] the secundary result is a consecutive worksheet area, a matrix with ??? rows and 22 columns
        ' [] all values of that area are copied into a memory matrix (to increase performance), ie assigned to an array with the name arrIN
        arrIN = .Range("B3", .Cells(.Rows.Count, "B").End(xlUp)).Resize(, 22)
    End With

    ' read source data
    For r = 1 To UBound(arrIN, 1)                   ' [] r represents the "row" number within our memory matrix and is increased by one every turn (Next r)
        iMax = Len(arrIN(r, 3))                     ' [] "column" 3 (on "row" r) of our matrix contains the "Time Out" numbers without delimiters, so determine how many numbers there are
        ' allocate memory for destination data
        ReDim arrOUT(1 To iMax, 1 To 6)             ' [] prepare a memory matrix with iMax rows and 6 columns for the purpose of output on destination sheet
        ' rearrange destination data
        For n = 1 To iMax                           ' [] on every turn (Next n) fill each row r with the required output
            iBlock = Mid(arrIN(r, 3), n, 1)         ' [] isolate from row r, column 3 (containing the "Time Out" numbers without delimiters), the required n-th number (length 1) and assign result to iBlock variable
            arrOUT(n, 1) = arrIN(r, 1)              ' [] copy NAME               (column 1) to output matrix (row n, column 1)
            arrOUT(n, 2) = iBlock                   ' [] copy isolated TIME OUT number      to output matrix (row n, column 2)
            arrOUT(n, 5) = arrIN(r, 21)             ' [] copy INC & TA          (column 21) to output matrix (row n, column 5)
            arrOUT(n, 6) = arrIN(r, 22)             ' [] copy SUBSTITUTE'S NAME (column 22) to output matrix (row n, column 6)
            Select Case iBlock
                Case 1                              ' [] depending on TIME OUT number, do copy ....
                    arrOUT(n, 3) = arrIN(r, 6)      ' [] ... row r, column 6 (Class 1)  to output matrix
                    arrOUT(n, 4) = arrIN(r, 7)      ' [] ... row r, column 7 (Room 1)
                Case 2
                    arrOUT(n, 3) = arrIN(r, 9)      ' [] etc.
                    arrOUT(n, 4) = arrIN(r, 10)
                Case 3
                    arrOUT(n, 3) = arrIN(r, 12)
                    arrOUT(n, 4) = arrIN(r, 13)
                Case 4
                    arrOUT(n, 3) = arrIN(r, 15)
                    arrOUT(n, 4) = arrIN(r, 16)
            End Select
        Next n
        
        ' determine destination area on sheet and paste rearranged data
        ' [] this part determines the first cell of the area within column A, which area is needed to paste the output to
        ' [] the resulting cell has to be extended (resized) with a certain number of rows and a certain number of columns so the arrOUT data fits in
        ' [] the 3 represents worksheet row to start with (row 2 contains headers) and is increased by value lRow on every turn (Next r)
        ' [] the iMax represents the number of needed rows, the 6 represents the number of needed columns
        ' [] finally, assign resulting worksheet area to the variable with the name rng
        Set rng = oWsDest.Range("A" & 3 + lRow).Resize(iMax, 6)
        
        ' [] all values previously placed in memory matrix are pasted into the above determined worksheet area.
        rng = arrOUT
        ' [] adjust target row to start with, with amount of already used rows
        lRow = lRow + iMax
    Next r

    ' finally create some headers
    With oWsDest.Range("A2:F2")
        .Font.Bold = True
        .EntireColumn.HorizontalAlignment = xlCenter
        .Cells(, 1).EntireColumn.HorizontalAlignment = xlGeneral
        ' [] within .Cells(row, column) the row number is omitted, so use the only and one row within range ("A2:F2")
        .Cells(, 1) = "Teacher Name"
        .Cells(, 2) = "Block"
        .Cells(, 3) = "Class"
        .Cells(, 4) = "Room"
        .Cells(, 5) = "Inc and TA"
        .Cells(, 6) = "Sub's Name"
    End With
    rng.EntireColumn.AutoFit
End Sub
 
Upvote 0
Solution

Forum statistics

Threads
1,215,523
Messages
6,125,317
Members
449,218
Latest member
Excel Master

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