简体   繁体   中英

Copy unknown range from specific worksheet

I am trying to do a copy in VBA, as part of a bigger macro so it needs to be in VBA, of an unknown range in a specific worksheet.

I have this code that work if I am in that worksheet:

Sub Copy()
Range("O2", Range("O" & Cells(Rows.Count, "A").End(xlUp).Row)).copy
End Sub()

And I have below that works for a specific range:

Sub Test()
    Worksheets("Data").Range("O2:O10").Copy
End Sub()

How can I make the second code work as unspecific.

Thanks,

The simplest & dirtiest solution is this one:

Range("O2:O" & Cells(Rows.Count, "A").End(xlUp).Row).Copy

or you can isolate the last row as a separate variable:

lastRow = Cells(Rows.Count, "A").End(xlUp).Row
Range("O2:O" & lastRow).Copy

at the end, one may decide to declare the range to be copied as a separate variable and to work with it, declaring the parent worksheet as well:

Public Sub TestMe()

    Dim lastRow As Long
    Dim ws As Worksheet
    Dim rangeToCopy As Range

    Set ws = workshetes("Sheet1")

    With ws
        lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
        Set rangeToCopy = .Range("O2:O" & lastRow)
        rangeToCopy.Copy
    End With

End Sub

And going really one step further is using a dedicated function for finding the last row per worksheet ( GitHub repo here ):

Function lastRow(wsName As String, Optional columnToCheck As Long = 1) As Long

    Dim ws As Worksheet
    Set ws = Worksheets(wsName)

    lastRow = ws.Cells(ws.Rows.Count, columnToCheck).End(xlUp).Row

End Function

You should practice to always fully qualify all your Sheet and Range objects.

The code below is a little long, but it's good practice to define and set all your objects and variables.

Code

Option Explicit

Sub Test()

Dim Sht As Worksheet
Dim LastRow As Long

' set your worksheet object
Set Sht = ThisWorkbook.Worksheets("Data")

With Sht
    ' get last row in column A
    LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row

    ' copy dynamic range in column O
    .Range("O2:O" & LastRow).Copy
End With

End Sub

At some point, your code will have to know the range that's going to be copied, right? You assign that to a variable and you use it.

Option Explicit 

Sub Test()
  Dim startRow as Long
  startRow = 'your method of determining the starting row
  Dim startCol as Long
  startCol = 'your method of determining the starting column
  Dim endRow as Long
  endRow = 'your method of determining the ending row (Last used row would work just fine)
  Dim endCol as Long
  endCol = 'your method of determining the ending column

  With Worksheets("Data")
    .Range(.Cells(startRow, startCol), .Cells(endRow, endCol)).Copy
  End with

End Sub

you could use a Function you pass the "seed" range to and returning a range from passed one to the last not empty cell in the same column, as follows (explanations in comments)

Function GetRange(rng As Range) As Range
    With rng.Parent ' reference passed range parent worksheet
        Set GetRange = .Range(rng, .Cells(.Rows.Count, rng.Column).End(xlUp)) ' return referenced sheet range from passed range to passed range column last not empty cell
    End With
End Function

to be used as follows:

Sub Test()
    GetRange(Worksheets("Data").Range("O2")).Copy
End Sub

you could enhance the function and have it handle a given "final" row

Function GetRange(rng As Range, Optional finalRow As Variant) As Range
    With rng.Parent ' reference passed range parent worksheet
        If IsMissing(finalRow) Then ' if no "final" row passed
            Set GetRange = .Range(rng, .Cells(.Rows.Count, rng.Column).End(xlUp)) ' return referenced sheet range from passed range to passed range column last not empty cell
        Else 'else
            Set GetRange = .Range(rng, .Cells(finalRow, rng.Column)) ' return referenced sheet range from passed range to passed range column cell in give "final" row
        End If
    End With

to be used as follows:

Sub Test()
    GetRange(Worksheets("Data").Range("O2"), 2).Copy
End Sub

having kept "final" row as optional, the function can be used with or without passing it:

Sub Test()
    GetRange(Worksheets("Data").Range("O2")).Copy ' this will copy worksheet "Data" range from row 2 down to its column "O" last not empty row
    GetRange(Worksheets("Data").Range("O2"), 3).Copy ' this will copy worksheet "Data" range from row 2 down to row 3
End Sub

You clearly don't enjoy using variables, so:

Worksheets("Data").Range("O2", Worksheets("Data").Range("O" & Cells(Rows.Count, "A").End(xlUp).Row)).copy

would suffice.

Generally, a more common solution would be to use intersect and CurrentRegion:

Application.intersect(Worksheets("Data").Range("O2").CurrentRegion,Worksheets("Data").Range("O2:O999999")).copy

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM