Home » excel » excel – Copying Multiple Ranges to Next Available Row

excel – Copying Multiple Ranges to Next Available Row

Posted by: admin May 14, 2020 Leave a comment

Questions:

I’m copying rows of data from one spreadsheet to another on a button press when cell I says “Yes” and deleting the original row of data. I have multiple ranges I’m copying from the same row, because the second spreadsheet doesn’t need all the data held in the first. (first spreadsheet has over 20 columns worth of data but the second has half that). Is there an easy way to make sure this all gets copied to the same row in the new spreadsheet?

Basically what I’m currently doing is copying each of the ranges to the corresponding column in the new spreadsheet with the row number set to being the last used row offset by 1. Which works fine if the previous cells actually have data in, but sometimes they don’t (the data is on households and some have more data than others so not all columns are always filled) so the data is placed in a different row from the rest of my data for that particular household.

Private Sub CommandButton1_Click()

Dim c As Range
Dim r As Integer
Dim LastRowD
Dim LastRowR
Dim Database As Worksheet
Dim DeReg As Worksheet


    'Set worksheet deignation as needed
    Set Database = ActiveWorkbook.Worksheets("Fostering Households")
    Set DeReg = ActiveWorkbook.Worksheets("De-Registrations")

    LastRowD = Database.Cells(Database.Rows.Count, "A").End(xlUp).Row

    'Searches all rows in I
    For Each c In Database.Range("I1:I" & LastRowD)

        'Catches cases where "Yes" is present in column I
        If c = "Yes" Then

            LastRowR = Database.Cells(Database.Rows.Count, "A").End(xlUp).Offset(1, 0)
            r = c.Row

            'Copies the desired column data from rows containing "Yes" from Database tab and pastes it in DeReg tab
            Database.Range("A" & r & ":G" & r).Copy DeReg.Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
            Database.Range("H" & r).Copy DeReg.Range("AJ" & Rows.Count).End(xlUp).Offset(1, 0)
            Database.Range("J" & r & ":X" & r).Copy DeReg.Range("H" & Rows.Count).End(xlUp).Offset(1, 0)
            Database.Range("AN" & r).Copy DeReg.Range("W" & Rows.Count).End(xlUp).Offset(1, 0)
            Database.Range("AS" & r).Copy DeReg.Range("X" & Rows.Count).End(xlUp).Offset(1, 0)
            Database.Range("AZ" & r & ":BH" & r).Copy DeReg.Range("Y" & Rows.Count).End(xlUp).Offset(1, 0)

        End If


    Next c

    For i = 250 To 1 Step -1

        If Database.Range("I" & i) = "Yes" Then
            Database.Rows(i).EntireRow.Delete
        End If

    Next i



End Sub

I’ve tried defining the last row based on whether “A” has data in (this is the only cell that is always used) with the code:

LastRowR = Database.Cells(Database.Rows.Count, "A").End(xlUp).Offset(1, 0) and then replacing my copy past code with:

Database.Range("A" & r & ":G" & r).Copy DeReg.Range("A" & LastRowR & ":B" & LastRowR).Row

But this didn’t work at all – it copied the first row it found with “Yes” in infinitely and overwrote all the data already present.
I also tried:

Database.Range("A" & r & ":G" & r).Copy DeReg.Range("A" & LastRowR).PasteSpecial

which also came with a world of problems and errors.
What I want is to search for the last used Row based on what’s in column A, offset by 1, and then past the data in the column I designate, rather than the last row used being defined by the column I’m trying to paste in – is this even doable? I can’t seem to find any information on this particular issue.

Also, if there is a better way of handing multiple ranges that would be great as it seems rather convoluted currently!

How to&Answers:

DeReg.Range("A" & Rows.Count).End(xlUp).Offset(1, 0) evaluates to:

DeReg.Range("A" & ActiveSheet.Rows.Count).End(xlUp).Offset(1, 0), so unless DeReg is the activesheet, you will get the wrong range.

See if this helps:

.... other code
'LastRowR = Database.Cells(Database.Rows.Count, "A").End(xlUp).Offset(1, 0)
r = c.Row

'Copies the desired column data from rows containing "Yes" from Database tab and pastes it in DeReg tab

    With Database
        LastRowR = DeReg.Range("A" & DeReg.Rows.Count).End(xlUp).Row + 1

        .Range("A" & r & ":G" & r).Copy DeReg.Range("A" & LastRowR)
        .Range("H" & r).Copy DeReg.Range("AJ" & LastRowR)
        .Range("J" & r & ":X" & r).Copy DeReg.Range("H" & LastRowR)
        .Range("AN" & r).Copy DeReg.Range("W" & LastRowR)
        .Range("AS" & r).Copy DeReg.Range("X" & LastRowR)
        .Range("AZ" & r & ":BH" & r).Copy DeReg.Range("Y" & LastRowR)
    End With

End If
... other code

Answer:

Some helpful tips:

  1. i is not declared. Declare as Long.
  2. LastRowR, r & LastRowD should be declared as Long.
  3. Replace ActiveWorkbook with ThisWorkbook.
  4. The copy paste method used may slow down the program, because this method copies and pastes both values and formatting.
  5. When you want to paste in the line after last row, use +1 (Example: LastRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row +1

Answer:

Just a couple thoughts. Firstly, you have declared multiple things that are unnecessary (IMO). I have adjusted your for loop to simply loop through a value that then references the range you want. This way you can use the i value a lot more efficiently than first setting a range and then looping through and referencing the row etc.

Additionally, based on the understanding I get from your post, if you use the .UsedRanged method your outputs will start at the last row on the new sheet, irregardless of your previously chosen method by column. I have not tested the below code, but it should guide you in a clearer way.

Option Explicit

Private Sub CommandButton1_Click()

Dim i As Long
Dim LastRowD As Long
Dim LastRowR As Long
Dim Database As Worksheet
Dim DeReg As Worksheet

'Set worksheet deignation as needed
Set Database = ActiveWorkbook.Worksheets("Fostering Households")
Set DeReg = ActiveWorkbook.Worksheets("De-Registrations")

LastRowD = Database.Cells(Database.Rows.Count, "A").End(xlUp).Row

'Searches all rows in I
For i = 1 To LastRowD
    'Catches cases where "Yes" is present in column I
    If Database.Range("I" & i) = "Yes" Then

        LastRowR = Database.UsedRange.Rows.Count + 1

        'Copies the desired column data from rows containing "Yes" from Database tab and pastes it in DeReg tab
        Database.Range("A" & i & ":G" & i).Copy DeReg.Range("A" & LastRowR)
        Database.Range("H" & i).Copy DeReg.Range("AJ" & LastRowR)
        Database.Range("J" & i & ":X" & i).Copy DeReg.Range("H" & LastRowR)
        Database.Range("AN" & i).Copy DeReg.Range("W" & LastRowR)
        Database.Range("AS" & i).Copy DeReg.Range("X" & LastRowR)
        Database.Range("AZ" & i & ":BH" & i).Copy DeReg.Range("Y" & LastRowR)

    End If

Next i

For i = 250 To 1 Step -1

    If Database.Range("I" & i) = "Yes" Then
        Database.Rows(i).EntireRow.Delete
    End If

Next i

End Sub