查找VBA中范围的最后一个单元格

4
如何查找定义范围内最后一个单元格的位置?该单元格不必包含任何数据,但必须是某个范围内最右边和最下方的单元格。
Set rngOrigin = wksOrigin.Cells(IntFirstRow, IntFirstColumn).CurrentRegion

I wish to receive

Cells(i,j)

1
这可能适用于简单情况 http://www.cpearson.com/excel/cells.htm,使用 set myrange=Range("A1:A10") 这种方式,并使用该链接中关于索引范围的内容,以及使用 myrange.Rows.Count。 - barlop
10个回答

7
也许这正是您想要的:
Dim rngLastCell As Range
Set rngLastCell = rngOrigin(rngOrigin.Count)

1
不是最优雅的,但肯定是最短的。对我来说有效! - Piotr L
如果范围是行或列,则它将无法工作,因为例如worksheets(1).rows("1:3").count返回3(行数),而不是这些行的单元格的总数。 - 6diegodiego9
1
适用于任何范围的正确安全解决方案应该是anyRange.Cells(anyRange.Cells.Count)。 - 6diegodiego9
1
不幸的是,这些简短的解决方案对于非连续范围,如Worksheets(1).Range("a1:b3, d5:e6")是无效的 :-( - 6diegodiego9
感谢@6diegodiego9的评论。使用worksheets(1).range("1:3").count代替worksheets(1).rows("1:3").count,或者使用他建议的anyRange.Cells(anyRange.Cells.Count)。对于非连续范围,上述解决方案将无法工作!另一个代码应该检查给定范围中最大的列和最大的行号。要检查给定范围是否为非连续范围,请使用If rngOrigin.Areas.Count > 1 Then '... - Jalal
显示剩余2条评论

2
也许您正在寻找以下内容:
'absolute indexes from cell A1
With rngOrigin
    i = .Rows(.Rows.count).row
    j = .Columns(.Columns.count).Column
End With

'relative indexes from rngOrigin upleftmost cell
With rngOrigin
    i = .Rows(.Rows.count).row - .Rows(1).row + 1
    j = .Columns(.Columns.count).Column - .Columns(1).Column + 1
End With

它无法为非连续范围提供正确的单元格,例如Worksheets(1).Range("a1:b4, d5:e6")。 - 6diegodiego9

1
其他人给出的答案大多数都是可以运作的,但是如果区域是由非连续单元格组成的联合体,则不行。这里有一个版本,可以始终适用于单个和多个区域,连续和非连续的情况。
Function LastCellOfRange(rng As Excel.Range) As Excel.Range
  Dim area As Excel.Range
  Dim rowNum As Long
  Dim maxRow As Long
  Dim colNum As Long
  Dim maxCol As Long
  Dim areaIdx As Integer

  Set LastCellOfRange = Nothing

  maxRow = 0
  maxCol = 0
  For areaIdx = 1 To rng.Areas.Count
    Set area = rng.Areas(areaIdx)
    rowNum = area.Cells(area.Cells.Count).row
    If (rowNum > maxRow) Then
      maxRow = rowNum
    End If
    colNum = area.Cells(area.Cells.Count).Column
    If (colNum > maxCol) Then
      maxCol = colNum
    End If
  Next areaIdx

  Set LastCellOfRange = rng.Worksheet.Cells(maxRow, maxCol)
  Set area = Nothing
End Function

1
我在下面的代码中处理了它,但是你的评论很有帮助。谢谢。
intLastRow = rngOrigin.Cells(1, 1).Row + rngOrigin.Rows.Count - 1
intLastCol = rngOrigin.Cells(1, 1).Column + rngOrigin.Columns.Count - 1

那么你应该采用我的“绝对”代码,避免重复使用rngOrigin并使用(对我来说)更合适的范围规定。 - user3598756
你的解决方案不能正确地给出非连续范围的最后一个单元格,例如Worksheets(1).Range("a1:b4, d5:e6")。 - 6diegodiego9

0
你可以尝试以下方法,但它依赖于单元格始终被填充。
rngOrigin.End(xlDown).End(xlRight)

或者您可以使用CurrentRegion,计算行数和列数,并使用Offset

另外,您还可以使用这种结构,即使基于整个行或整个列的范围也可以使用。

Sub Test()
    Dim rngOrigin As Excel.Range
    Set rngOrigin = Range("$A$1:$D$6")

    Dim rngLast As Excel.Range
    Set rngLast = rngOrigin.Cells(rngOrigin.Cells.Count)
    Debug.Print rngLast.Address
End Sub

最后,对于包含多个区域的范围,您需要编写针对范围的区域集合的脚本。
Sub Test()
    Dim rngOrigin As Excel.Range
    Set rngOrigin = Range("$A$1:$D$6,$F$1:$G$6")
    
    Debug.Print rngOrigin.Areas(1).Cells(rngOrigin.Areas(1).Cells.Count).Address
    Debug.Print rngOrigin.Areas(2).Cells(rngOrigin.Areas(2).Cells.Count).Address

End Sub

这是错误的,因为范围结束属性只会移动到当前区域内的最后一个单元格。End(xlDown)或End(XlToRight)与从给定范围的左上角单元格开始按CTRL+箭头向下或CTRL+箭头向右相同。 - 6diegodiego9
@6diegodiego9 感谢您的反馈。我已经修改了答案。 - S Meaden

0

这是用于非连续范围的

`Sub GetLastCellFromRange() Dim rng As Range

Set rng = Range(Range("$C$10:$E$20"), Range("$G$10:$H$50"))

'Set rng = Range(Selection.Address) ' Use this line to select the range in worksheet

MsgBox "Last Cell of given range is : " & rng.Cells(rng.Rows.Count, rng.Columns.Count).Address

结束子程序


0
使用此代码查找给定范围内的最后一个单元格。
Sub GetLastCellFromRange()
    Dim rng As Range

    Set rng = Range("$C$10:$E$20")

    'Set rng = Range(Selection.Address) ' Use this line to select the range in worksheet

    MsgBox "Last Cell of given range is : " & rng.Cells(rng.Rows.Count, rng.Columns.Count).Address
End Sub

我希望它能对你有所帮助


它无法为非连续范围提供正确的最后单元格,例如Worksheets(1).Range("a1:b4, d5:e6")。 - 6diegodiego9
是的,上述代码仅适用于连续范围。 - Shashiraju
用于非连续范围的代码: Sub GetLastCellFromRange() Dim rng As RangeSet rng = Range(Range("$C$10:$E$20"), Range("$G$10:$H$50")) ' 可使用如下代码在工作表中选择范围 ' Set rng = Range(Selection.Address) MsgBox "给定范围的最后一个单元格为:" & rng.Cells(rng.Rows.Count, rng.Columns.Count).AddressEnd Sub - Shashiraju

0

许多答案在给定范围连续的情况下都可以工作。这是我会用于您绝对确定将是连续的范围:

Sub test()
    Dim myRng As Range, lastCell As Range
    Set myRng = Range("A1:D4")
    Set lastCell = myRng.Cells(myRng.Rows.Count, myRng.Columns.Count)
    Debug.Print lastCell.Address 'returns $D$4
End Sub

对于非连续的情况,DB用户10082797提供了一个很好的解决方案,但是当范围被对角线上升放置时,他们的函数会失败(例如,如果您传递rng=A3:B4,C1:D2,则输出为D4,这不是原始范围的一部分。)

因此问题变成了,范围A3:B4,C1:D2中的最后一个单元格是什么?是B4还是D2?这是程序员的决定。这是我根据DB用户10082797的函数编写的一个函数:

Function LastCellOfRange(rng As Range, Optional returnLastRow As Boolean = True) As Range
'returns the last cell in @rng.
'if @returnLastRow is TRUE, then the output will always be in the right most cell of the last row of @rng
'if @returnLastRow is FALSE, then the output will always be in the bottom most cell of the last column of @rng
'(@returnLastRow only matters for non-contiguous ranges under certain circumstances.)
    'initialize variables
    Dim area As Range, areaIdx As Long
    Dim lastCellInArea As Range
  
    'loop thru each area in the selection
    For areaIdx = 1 To rng.Areas.Count
        Set area = rng.Areas(areaIdx) 'get next area
        Set lastCellInArea = area.Cells(area.Rows.Count, area.Columns.Count) 'get the last cell in the area
        'if:
        '  the return is empty
        '  OR if the last row needs to be returned and this row is larger than the last area's
        '  OR if the last row needs to be returned and this row is the same as the last area's but has a larger column
        '  OR if the last column needs to be returned and this column is larger than the last area's
        '  OR if the last column needs to be returned and this column is the same as the last area's but has a larger row
        'THEN:
        '  make this cell the return range
        If LastCellOfRange Is Nothing Then
            Set LastCellOfRange = lastCellInArea '(must be seperate from the other statment when its not set to anything)
        ElseIf _
            returnLastRow = True And lastCellInArea.Row > LastCellOfRange.Row _
            Or returnLastRow = True And lastCellInArea.Row = LastCellOfRange.Row And lastCellInArea.Column > LastCellOfRange.Column _
            Or returnLastRow = False And lastCellInArea.Column > LastCellOfRange.Column _
            Or returnLastRow = False And lastCellInArea.Column = LastCellOfRange.Column And lastCellInArea.Row > LastCellOfRange.Row _
        Then
            Set LastCellOfRange = lastCellInArea
        End If
    Next areaIdx
End Function

您可以像这样使用该函数:
Sub test()
    Dim myRng As Range
    Set myRng = Range("A3:B4,C1:D2")
    Debug.Print LastCellOfRange(myRng).Address 'returns $B$4
    Debug.Print LastCellOfRange(myRng, False).Address 'returns $D$2
End Sub

-1
如果您想获取一个已定义范围内的最后一个单元格,无论其是否包含任何内容,这里有一个简单的解决方案。
Dim InputRng As Range    'define a range for the test'
Set InputRng = Range("$F$3:$F$15") 
MsgBox InputRng(1).Address & ":" & InputRng(InputRng.Cells.Count).Address    'This would output the absolute address of defined range' 

enter image description here


虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅链接的答案可能会失效。-【来自审查】 - Dez
@Dez:谢谢你的提示,我有时间会去做。 - Nelson Yang
就像我回复Dez的时候说的,我会在我有时间的时候去做。我正在开发Excel中的UDF函数,它执行类似的功能,并且我首先查看了堆栈,但没有找到任何对我的情况有用的答案。最终,我从我在答案中提供的另一个网站上得到了解决方案。我已经测试过了,它可以正常工作。 - Nelson Yang
它无法为非连续范围提供正确的最后单元格,例如Worksheets(1).Range("a1:b4, d5:e6")。 - 6diegodiego9

-1
在您的情况下,由于您想要找到工作表wksOrigin(定义为工作表)中最右边和最下面的单元格,因此您可以使用SpecialCells(xlCellTypeLastCell)来获取最后一个单元格的行和列。
i = wksOrigin.Cells.SpecialCells(xlCellTypeLastCell).Row ' <-- get last row number
j = wksOrigin.Cells.SpecialCells(xlCellTypeLastCell).Column ' <-- get last column number

如果您想调试您的结果,您可以添加以下代码:
MsgBox "Last row at " & i & ", last column at " & j

1
我想找到当前区域的最后一个单元格,而不是整个工作表。如果工作表包含超出当前区域的数据,我不想将它们包括在内。 - Fajka
你定义的范围是什么? - Shai Rado

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接