-1

I need your help. I'm trying to run a macro on every row of a table. I want to have the first and the last interaction date with all clients of the list. What I already did on a macro is to copy the first date from a sheet2 and paste it on sheet1 to get the first date, then with CTRL-Down do it again with the next date to get the last date. However, since it's not a loop, it only does it on the cells I did it. (Down is the code I have). I would like the code to do the same thing on every cell, until the end of the table.

I have attached screenshot of the two sheets. I hope I made myself clear and I hope someone can help you out.

sheet1 sheet2

Sheets("Total").Select
    Range("D6923").Select
    Selection.End(xlDown).Select
    Selection.Copy
    Sheets("Timeline").Select
    ActiveSheet.Paste
    Range("C189").Select
    Sheets("Total").Select
    Selection.End(xlDown).Select
    Application.CutCopyMode = False
    Selection.Copy
    Sheets("Timeline").Select
    ActiveSheet.Paste
    Range("B190").Select
    Sheets("Total").Select
    Selection.End(xlDown).Select
    Application.CutCopyMode = False
    Selection.Copy
    Sheets("Timeline").Select
    ActiveSheet.Paste
    Range("C190").Select
    Sheets("Total").Select
    Selection.End(xlDown).Select
    Application.CutCopyMode = False
    Selection.Copy
    Sheets("Timeline").Select
    ActiveSheet.Paste
Scott Holtzman
  • 27,099
  • 5
  • 37
  • 72
  • 3
    Have you even researched how to do a loop in Excel VBA? If so, update your question the looping code you have tried and where its failing. – Scott Holtzman Aug 04 '20 at 15:10
  • You should simplify and make your code more robust by getting rid of all those [`.Select`'s](https://stackoverflow.com/questions/10714251/how-to-avoid-using-select-in-excel-vba) – Ron Rosenfeld Aug 04 '20 at 15:29
  • @Scott HoltzmanI have been readying about it but I don't have it clear how to apply it to this code. I'm new at this. – Maria D. Barrantes Aug 04 '20 at 15:58

1 Answers1

1

I can see you are very new to this and that is fine, we all were once! Using recorded macros is a good way to see how excel views what you are doing at the time but it is extremely inefficient compared to what it could be. As Ron has mentioned, select really is not a friend of efficient code. For example, your first four lines could be rewritten into one line as:

Sheets("Total").Range("D6923").End(xlDown).copy

However even this isn't the best way. I'm going to assume that you are working from the top of your sheet to the bottom and answer your question based on what I think you are trying to do. I'm also assuming that your sheet called Timeline is sheet 1 and your sheet called Total is sheet 2. Within total I am assuming that any number of entries could be there rather than just the two shown in the three examples given.

Sub ExampleCode()
  'Variables, you can create and store things in VBA to make life easier for you
  Dim Wb as Workbook            'This is the workbook you are using
  Dim wsTimeline as Worksheet   'This is your worksheet called Timeline
  Dim wsTotal as Worksheet      'This is your worksheet called as Total
  Const rMin as byte = 5        'This is where the loop will start, I'm assuming row 5. As _
                                   this won't change throughout the code and we know it at the _
                                   start it can be a constant
  Dim rMax as long              'This will be the last row in your loop
  Dim r as long                 'This will be how your loop knows which row to use
  Dim timelineRow as long       'This will be the row that the data is pasted in Timeline
  Dim timelineLastRow as Long   'This is the last row of data in your timeline sheet
  
  Set Wb = Thisworkbook                   'Your whole workbook is now stored in the variable Wb
  Set wsTimeline = Wb.Sheets("Timeline")  'As the workbook was stored in Wb we can use it as _
                                             shorthand here. Now the sheet Timeline is in wsTimeline
  Set wsTotal = Wb.Sheets("Total")        'Same as above, this sheet is now stored

  rMax = wsTotal.Cells(Rows.Count, 1).End(xlUp).Row  'This is the equivalent of starting at the _
                                                        bottom row in column A and pressing _
                                                        Ctrl+Up. This takes you to the last _
                                                        row of data in column A. …(Rows.Count, 2)… _
                                                        would be column B etc.
  timelineLastRow = wsTimeline.Cells(Rows.Count, 1).End(xlUp).Row
  
  'This is the bit where you start to loop, the line below basically says "Do the code in this _
     loop for every value between rMin and rMax, each time make 'r' that value (r for row!)

  With wsTotal                                'Means that anything below starting with '.' will _
                                                 be the same as 'wsTotal.'
    For r = rMin To rMax
      'Ensure working on a line with data
      If .Cells(r, 1) = "" Then
        r = .Cells(r, 1).end(xlDown).row
        If r > rMax Then
          End With                            'Closes the With statement above as no longer needed.
          Exit For                            'Exits the loop as we have ended up beyond rMax
        End if
      End if
      
      'This will look for the person in wsTimeline and if they aren't there then add them
      If IsError(Application.Match(.Cells(r, 1), wsTimeline.Range("A3:A" & timelineLastRow), 0)) Then
        wsTimeline.Cells(timelineLastRow + 1, 1) = wsTotal.Cells(r, 1)
        timelineRow = timeLineLastRow + 1
        timelineLastRow = timelineRow
      Else
        timelineRow = Application.Match(.Cells(r, 1), wsTimeline.Range("A3:A" & timelineLastRow), 0)
      End If

      'I'm assuming that all records in 'Total' are chronologically ascending with no gaps between _
         each row for a single person.
      wsTimeline.Cells(timelineRow, 3) = .Cells(r + 2, 4)
      If .cells(r + 3, 4) <> "" then
        wsTimeline.Cells(timelineRow, 4) = .Cells(r + 2, 4).End(xlDown)
      Else
        wsTimeline.Cells(timelineRow, 4) = .Cells(r + 2, 4).End(xlDown)
      End If
      
      'Now that the data has been brought across from Total to Timeline we can move on to _
         the next row.
    Next r     'This will add one to the value stored in r and start the code again where _
                  the loop started
  End With

  'The loop has now ended having gone through every row in your worksheet called Total.
End Sub
  • Will, I will try it like this right away. Thank you SO MUCH! You got it right, I am very new at this. I sincerely appreciate you taking the time to help me. Have a good one! – Maria D. Barrantes Aug 04 '20 at 20:19