非连续范围中的最后一行或单元格{NOT a Worksheet search}

时间:2016-06-15 19:02:21

标签: vba excel-vba excel

首先,这不是典型的新手问题。我试图在我已经正确创建的范围内找到最后一行(或单元格)。

在这个例子中,我有两个范围合并为一个与联合。在整个范围内循环,我得到了我想要的数据,而且事情很有效。

Sub Test()

    Dim unionRange As Range, currentRow As Range
    Set unionRange = Union(Range("A3:C5"), Range("A8:C11"))

    For Each currentRow In unionRange.Rows
        Debug.Print "Row: " & currentRow.row
    Next currentRow

End Sub

给出了这些结果

Row: 3
Row: 4
Row: 5
Row: 8
Row: 9
Row: 10
Row: 11

但是当我想确定当前行是否是我范围内的最后一行时,我似乎无法找到一种干净的方式来获取该信息。

Sub Test()

    Dim unionRange As Range, currentRow As Range
    Set unionRange = Union(Range("A3:C5"), Range("A8:C11"))

    For Each currentRow In unionRange.Rows
        Dim lastRowIndex As Integer

        'lastRowIndex = unionRange. ???

        If currentRow.row = lastRowIndex Then
            MsgBox ("Last Row")
        End If

    Next currentRow

End Sub

它之所以如此困难,是因为我尝试过的每个解决方案只会在第一个连续组中生成信息,如下所示。

    Debug.Print unionRange.Rows.Count ' 3 (should be 7)
    Debug.Print unionRange.Rows(unionRange.Rows.Count).row ' 5 (should be 11)

除了在此之前进行第二次循环外,还有其他方法可以获取最后一行的地址信息吗?

2 个答案:

答案 0 :(得分:6)

您需要使用范围的Areas属性。当范围不连续时,它包含多个区域。每个区域都是子范围。不幸的是,区域没有以任何方式排序。因此,您需要检查循环中的每个区域,然后返回最大行。

在下面的示例中,我创建了一个函数,该函数为您提供非连续范围内的最后一个行号。测试子将行号打印到Visual Basic for Applications编辑器中的立即窗口。

Public Function GetLastRowOfNonContiguousArea(targetRange As Range) As Long
    Dim subRange As Range
    Dim maxRow As Long, areaMaxRow As Long

    maxRow = 0

    For Each subRange In targetRange.Areas
        areaMaxRow = subRange.Rows(subRange.Rows.Count).Row
        If areaMaxRow > maxRow Then maxRow = areaMaxRow
    Next subRange

    GetLastRowOfNonContiguousArea = maxRow
End Function

Public Sub test()
    Dim testRange As Range

    Set testRange = Union([A5:A9], [E20:F21], [C1:C3])

    Debug.Print GetLastRowOfNonContiguousArea(testRange)
End Sub

答案 1 :(得分:0)

在下一行是空的情况下,某个范围内的“最后”行不是?在这种情况下,以下应该可以解决问题:

Sub Test()

Dim unionRange As Range, currentRow As Range
Set unionRange = Union(Range("A3:C5"), Range("A8:C11"))

For Each currentRow In unionRange.Rows
    Dim lastRowIndex As Integer

    If currentRow.Cells(1, 1).Offset(1, 0).Value = vbNullString Then
        MsgBox "Last Row in " & currentRow.Row
    End If

Next currentRow

End Sub

更新

感谢@AndASM我今天刚刚学到了新东西!!我对Areas一无所知!所以,请不要将我的答案标记为正确答案(即使这可以解决您的问题)。

然而,我想提供以下代码,因为我相信这可能更符合您的需求:

Sub Test()

Dim unionRange As Range, currentRow As Range, subArea As Range
Set unionRange = Union(Range("A3:C5"), Range("A8:C11"))

For Each currentRow In unionRange.Rows
    For Each subArea In unionRange.Areas
        If Not Intersect(subArea, currentRow) Is Nothing Then
            If currentRow.Row = subArea.Row + subArea.Rows.Count - 1 Then
                MsgBox "Last Row in " & currentRow.Row
            End If
        End If
    Next subArea
Next currentRow

End Sub