Home > Enterprise >  Copy paste rows until change in value in Column B into the next empty column in another Sheet
Copy paste rows until change in value in Column B into the next empty column in another Sheet

Time:08-02

I have a data in Excel Sheet1, which is as follows:

enter image description here

I have to organize the data where I want to copy all the data rows based on "Column B" into a separate sheet until the last unique value in "Column B", which is shown below: I have around 6000 rows in my data set.

enter image description here

I have developed the following VBA code which copy every 6 rows and paste it in the last empty column in Sheet2. as shown below.

Sub copyPaste()

    Dim x As Long
    Dim y As Long
    Dim lastRow As Long

    Dim sht As Worksheet
    Set sht = Worksheets("Sheet1")
    
    y = 6
    lastRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
    'emptyColumn = Sheet2.Cells(2, Columns.Count).End(xlToLeft).Column

    For x = 2 To lastRow Step 6
        If Worksheets("Sheet2").Cells(2, "A") = "" Then
            Worksheets("Sheet1").Range("A" & x & ":D" & y).Copy _
                    Destination:=Worksheets("Sheet2").Cells(2, "A")
        Else
            Worksheets("Sheet1").Range("A" & x & ":D" & y).Copy _
                    Destination:=Worksheets("Sheet2").Cells(2, Columns.Count).End(xlToLeft).Offset(, 1)
        End If
        y = y   6
    Next
End Sub

enter image description here

I kindly request if any of you have a solution to organize the data, as shown in image 2 above.

CodePudding user response:

Assuming your data is sorted on Person:

Sub copyPaste()
    Dim wsSource As Worksheet, cDest As Range, c As Range, n As Long
    
    Set wsSource = Worksheets("Sheet1")            'source data sheet
    Set c = wsSource.Range("B2")                   'first person name
    
    Set cDest = Worksheets("Sheet2").Range("A1")   'first paste destination
    
    Do While c.Value <> ""                                      'loop while have a name
        n = Application.CountIf(wsSource.Columns("B"), c.Value) 'how many rows for this person?
        c.Offset(0, -1).Resize(n, 4).Copy cDest                 'copy data over
        Set c = c.Offset(n)                                     'next name
        Set cDest = cDest.Offset(0, 4)                          'next paste location
    Loop
End Sub

CodePudding user response:

Stack Unique Rows Side By Side

  • If copying the values (no formats or formulas) is good enough, you could use the following.
Option Explicit

Sub StackUniqueRowsSideBySide()
    
    ' Reference the workbook.
    Dim wb As Workbook: Set wb = ThisWorkbook
    
    ' Reference the source worksheet ('sws').
    Dim sws As Worksheet: Set sws = wb.Worksheets("Sheet1")
    
    Dim srg As Range
    
    ' Reference the source range.
    With sws.Range("A1").CurrentRegion
        Set srg = .Resize(.Rows.Count - 1).Offset(1)
    End With
    
    ' Using the 'GetUniqueRowsSideBySide' function,
    ' return the stacked unique rows in a 2D one-based array ('dData').
    Dim dData As Variant: dData = GetUniqueRowsSideBySide(srg, 3, 0)
    
    ' Reference the destination worksheet ('dws').
    Dim dws As Worksheet: Set dws = wb.Worksheets("Sheet2")
    
    ' Reference the destination first cell ('dfCell').
    Dim dfCell As Range: Set dfCell = dws.Range("A2")
        
    Dim drg As Range
        
    ' Reference the destination clear range ('drg').
    Set drg = dfCell.Resize(dws.Rows.Count - dfCell.Row   1, _
        dws.Columns.Count - dfCell.Row   1)
    ' Clear previous data.
    drg.Clear
    
    ' Reference the destination range ('drg').
    Set drg = dfCell.Resize(UBound(dData, 1), UBound(dData, 2))
    ' Write new data.
    drg.Value = dData

End Sub

Function GetUniqueRowsSideBySide( _
    ByVal srg As Range, _
    Optional ByVal UniqueColumn As Long = 1, _
    Optional ByVal ColumnGap As Long = 0) _
As Variant
    
    ' Write the number of source rows and columns
    ' to variables ('srCount', 'scCount').
    Dim srCount As Long: srCount = srg.Rows.Count
    Dim scCount As Long: scCount = srg.Columns.Count
    
    ' Write the values from the source range to a 2D one-based array,
    ' the source array ('sData').
    Dim sData() As Variant: sData = srg.Value
    
    ' Create and reference a new dictionary object ('dict').
    Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
    dict.CompareMode = vbTextCompare ' case-insensitive
    
    Dim sKey As Variant
    Dim sr As Long
    
    ' Write each unique value from the unique column ('UniqueColumn')
    ' of the source array to a 'key' of the dictionary and write
    ' the current row to the collection held in the associated 'item'.
    For sr = 1 To srCount
        sKey = sData(sr, UniqueColumn)
        If Not dict.Exists(sKey) Then
            Set dict(sKey) = New Collection
        End If
        dict(sKey).Add sr
    Next sr
            
    Dim drCount As Long
    
    ' Determine the destination rows count ('drCount'),
    ' the number of items in the largest collection ('dict(sKey)').
    For Each sKey In dict.Keys
        If dict(sKey).Count > drCount Then drCount = dict(sKey).Count
    Next sKey
    
    ' Calculate the destination columns count ('drCount').
    Dim dcCount As Long
    dcCount = dict.Count * (scCount   ColumnGap) - ColumnGap
    
    ' Define the destination array ('dData').
    Dim dData() As Variant: ReDim dData(1 To drCount, 1 To dcCount)
     
    Dim sItem As Variant
    Dim sk As Long
    Dim sc As Long
     
    Dim dr As Long
    Dim dcOffset As Long
     
    ' Using the information in the dictionary, return the stacked unique rows
    ' from the source array in the destination array.
    For Each sKey In dict.Keys
        sk = sk   1
        dcOffset = (sk - 1) * (scCount   ColumnGap)
        For Each sItem In dict(sKey)
            dr = dr   1
            For sc = 1 To scCount
                dData(dr, sc   dcOffset) = sData(sItem, sc)
            Next sc
        Next sItem
        dr = 0
    Next sKey
    
    ' Assign the destination array to the result of the function.
    GetUniqueRowsSideBySide = dData
    
End Function
  • Related