What does the Excel range.Rows property really do?

前端 未结 9 1838
故里飘歌
故里飘歌 2021-01-30 16:21

OK, I am finishing up an add-on project for a legacy Excel-VBA application, and I have once again run up against the conundrum of the mysterious range.Rows (?) and

相关标签:
9条回答
  • 2021-01-30 16:26

    Range.Rows, Range.Columns and Range.Cells are Excel.Range objects, according to the VBA Type() functions:

    ?TypeName(Selection.rows)
    Range
    
    However, that's not the whole story: those returned objects are extended types that inherit every property and method from Excel::Range - but .Columns and .Rows have a special For... Each iterator, and a special .Count property that aren't quite the same as the parent Range object's iterator and count.

    So .Cells is iterated and counted as a collection of single-cell ranges, just like the default iterator of the parent range.

    But .Columns is iterated and counted as a collection of vertical subranges, each of them a single column wide;

    ...And .Rows is iterated and counted as a collection of horizontal subranges, each of them a single row high.

    The easiest way to understand this is to step through this code and watch what's selected:

    Public Sub Test() 
    Dim SubRange As Range Dim ParentRange As Range
    Set ParentRange = ActiveSheet.Range("B2:E5")

    For Each SubRange In ParentRange.Cells SubRange.Select Next
    For Each SubRange In ParentRange.Rows SubRange.Select Next
    For Each SubRange In ParentRange.Columns SubRange.Select Next
    For Each SubRange In ParentRange SubRange.Select Next
    End Sub
    Enjoy. And try it with a couple of merged cells in there, just to see how odd merged ranges can be.

    0 讨论(0)
  • 2021-01-30 16:26

    Your two examples are the only things I have ever used the Rows and Columns properties for, but in theory you could do anything with them that can be done with a Range object.

    The return type of those properties is itself a Range, so you can do things like:

    Dim myRange as Range
    Set myRange = Sheet1.Range(Cells(2,2),Cells(8,8))
    myRange.Rows(3).Select
    

    Which will select the third row in myRange (Cells B4:H4 in Sheet1).

    update: To do what you want to do, you could use:

    Dim interestingRows as Range
    Set interestingRows = Sheet1.Range(startRow & ":" & endRow)
    

    update #2: Or, to get a subset of rows from within a another range:

    Dim someRange As Range
    Dim interestingRows As Range
    
    Set myRange = Sheet1.Range(Cells(2, 2), Cells(8, 8))
    
    startRow = 3
    endRow = 6
    
    Set interestingRows = Range(myRange.Rows(startRow), myRange.Rows(endRow))
    
    0 讨论(0)
  • 2021-01-30 16:34

    Since the .Rows result is marked as consisting of rows, you can "For Each" it to deal with each row individually, like this:

    Function Attendance(rng As Range) As Long
    Attendance = 0
    For Each rRow In rng.Rows
        If WorksheetFunction.Sum(rRow) > 0 Then
            Attendance = Attendance + 1
        End If
    Next
    End Function
    

    I use this to check attendance in any of a few categories (different columns) for a list of people (different rows).

    (And of course you could use .Columns to do a "For Each" over the columns in the range.)

    0 讨论(0)
  • 2021-01-30 16:34

    I've found myself using range.Rows for its effects in the Copy method. It copies the height of the rows from the origin to the destination, which is the behaviour I want.

    rngLastRecord.Rows.Copy Destination:=Sheets("Availability").Range("a" & insertRow)
    

    If I had used rngLastRecord.Copy instead of rngLastRecord.Rows.Copy, the row heights would be whatever was there before the copy.

    0 讨论(0)
  • 2021-01-30 16:35

    I'm not sure, but I think the second parameter is a red herring.

    Both .Rows and .Columns take two optional parameters: RowIndex and ColumnIndex. Try to use ColumnIndex, e.g. Rows(ColumnIndex:=2), generates an error for both .Rows and .Columns.

    My feeling it's inherited in some sense from the Cells(RowIndex,ColumnIndex) Property but only the first parameter is appropriate.

    0 讨论(0)
  • 2021-01-30 16:35

    There is another way, take this as example

    Dim sr As String    
    sr = "6:10"
    Rows(sr).Select
    

    All you need to do is to convert your variables iStartRow, iEndRow to a string.

    0 讨论(0)
提交回复
热议问题