Reputation: 169
I have a table with data arranged in groups from 1 to 10. Each group have one or more rows. I want to copy data only from the first row of each group and paste it to another sheet. What is the correct approach to achieve this? So far, all my attempts to create a loop with condition were unsuccessful. Any help or push in the right direction is highly appreciated in advance.
Sub GenerateReport()
Dim RowCountCopy As Integer
Dim RowCountPaste As Integer
RowCountCopy = 2
RowCountPaste = 3
For i = 1 To 10
Sheets("Sheet2").Range("A" & RowCountPaste) = Sheets("Sheet1").Range("A" & RowCountCopy)
Sheets("Sheet2").Range("B" & RowCountPaste) = Sheets("Sheet1").Range("B" & RowCountCopy)
Sheets("Sheet2").Range("C" & RowCountPaste) = Sheets("Sheet1").Range("F" & RowCountCopy)
RowCountCopy = RowCountCopy + 1
RowCountPaste = RowCountPaste + 1
Next i
End Sub
This is what generate the code without any conditions loops.
This is what I want to achieve.
Upvotes: 0
Views: 198
Reputation: 1420
Because you are working with tables, here is my approach. The code has some comments, but debug step by step to better understand if necessary.
Sub copyFirstRowOfEachGroup()
Dim ws As Worksheet: Set ws = ActiveSheet
Dim ol As ListObject: Set ol = ws.ListObjects(1)
Dim olColOrder As ListColumn, olColRank As ListColumn
Dim olColRng As Range
On Error GoTo errhandler
' Add temporary columns: Order & Rank
Set olColOrder = ol.ListColumns.Add: olColOrder.Name = "Order"
Set olColRank = ol.ListColumns.Add: olColRank.Name = "Rank"
' create an order depending on the ROW
Set olColRng = olColOrder.DataBodyRange
olColRng.FormulaR1C1 = "=[@Group]+ROW(R[1]C[1])/100000"
' set the rank in each goup
Set olColRng = olColRank.DataBodyRange
olColRng.FormulaR1C1 = "=COUNTIFS([Group],[@Group],[Order],""<""&[@Order])+1"
' set advanced filter criteria
ws.Range("M1").Value = "Rank"
ws.Range("M2").Value = 1
Dim crtRng As Range: Set crtRng = ws.Range("M1:M2")
' set destination range
ws.Range("G1").Value = "ID"
ws.Range("H1").Value = "Name"
ws.Range("I1").Value = "Group"
Dim dstRng As Range: Set dstRng = ws.Range("G1:I1")
' advanced filter
ol.Range.AdvancedFilter _
Action:=xlFilterCopy, _
CriteriaRange:=crtRng, _
CopyToRange:=dstRng, _
Unique:=False
' delete temporay columns and advanced filter criteria
crtRng.ClearContents
olColOrder.Delete
olColRank.Delete
errRoutine:
' clean
Set crtRng = Nothing
Exit Sub
errhandler:
Debug.Print Err.Number, Err.Description
Resume errRoutine
End Sub
Here is my file: https://www.dropbox.com/s/r42riiylcss5j7w/CopyWithCriteria.xlsm?dl=0
Upvotes: 0
Reputation: 42236
Please, try the next code:
Sub returnGropFirsRow()
Dim sh1 As Worksheet, sh2 As Worksheet, lastR1 As Long, arr, arrFin, i As Long, k As Long
Set sh1 = Worksheets("Sheet1")
Set sh2 = Worksheets("Sheet2")
astR1 = sh1.Range("A" & sh1.rows.count).End(xlUp).row 'last row in sh1
arr = sh1.Range("A1:F" & lastR1).value 'put the range in an array to make the code faster
ReDim arrFin(1 To 3, 1 To UBound(arr) + 1): k = 1 'redim the final array to have place for all possible cases
arrFin(1, k) = "ID": arrFin(2, k) = "Name": arrFin(3, k) = "Group" 'put the header in the final array
For i = 2 To UBound(arr) 'iterate between the arr elements
If arr(i, 6) <> arr(i - 1, 6) Then 'if arr element not equal with the one above it:
k = k + 1 'increment k (future row) variable
arrFin(1, k) = arr(i, 1): arrFin(2, k) = arr(i, 2): arrFin(3, k) = arr(i, 6) 'load the necessary elements in the final array
End If
Next i
ReDim Preserve arrFin(1 To 3, 1 To k) 'redim final array in order to keep only the filled values
'drop the array content at once and format the range:
Dim arrBord, El
arrBord = Application.Evaluate("Row(7:12)")
With sh2.Range("A1").Resize(UBound(arrFin, 2), UBound(arrFin))
.value = Application.Transpose(arrFin)
.EntireColumn.AutoFit
For Each El In arrBord
With .Borders(El)
.LineStyle = xlContinuous: .Weight = xlThin: .ColorIndex = 0
End With
Next El
.BorderAround , xlMedium
With .Range(.cells(1, 1), .cells(1, 3))
.Font.Bold = True
.BorderAround , xlMedium
.Interior.ColorIndex = 20
.HorizontalAlignment = xlCenter
End With
End With
End Sub
Upvotes: 1