首页 文章

查找仅包含最后一行的第一个单元格的范围?

提问于
浏览
0

我需要计算一个只包含一个单元格的范围 . 此单元格来自最后一行和第一列 . 如果工作表为空,则范围为 A1:A1 .

我知道有很多方法可以计算最后一行,但我正在寻找一种优雅的方法来获得最后一行的第一个单元格 . 也许一些例子更好地解释 .

示例#1

A B C D
1
2  X
3      X
4    X

结果#1

Range = A4:A4

例#2

A B C D
1

结果#2

Range = A1:A1

这该怎么做?

4 回答

  • 0

    上次使用的行和指定列交点专长 . UsedRange

    优雅的方法之一是使用 UsedRange 属性 .

    高级版

    '*******************************************************************************
    ' Purpose:    Using the UsedRange Property, creates a reference to the cell    *
    '             range at the intersection of the last used row and a specified   *
    '             column in a worksheet and prints its address and the address     *
    '             of the UsedRange to the Immediate Window.                        *
    '*******************************************************************************
    Sub LastUR_Column_UsedRange()
    
      Const cVntCol As Variant = "A"  ' Column
      Dim objRngT As Range            ' Target Range
    
      With ThisWorkbook.Worksheets("Sheet1")
        If .Cells(.UsedRange.Rows.Count + .UsedRange.Row - 1, cVntCol).Row = 1 _
            And .Cells(1, Columns.Count).End(xlToLeft).Column = 1 _
            And IsEmpty(.Cells(1, 1)) Then
          Debug.Print "objRngT = Nothing (Empty Worksheet)"
         Else
          Set objRngT = .Cells(.UsedRange.Rows.Count + .UsedRange.Row - 1, cVntCol)
          Debug.Print "objRngT = " & objRngT.Address & " calculated from the " _
              & "used range (" & .UsedRange.Address & ")."
          Set objRngT = Nothing
        End If
      End With
    
    End Sub
    '*******************************************************************************
    

    课程版

    '*******************************************************************************
    ' Purpose:    Using the UsedRange Property, creates a reference to the cell    *
    '             range at the intersection of the last used row and a specified   *
    '             column in a worksheet and prints subresults and  its address     *
    '             to the Immediate Window.                                         *
    '*******************************************************************************
    Sub LastUR_Column_UsedRange_Lesson()
    
      ' When you declare the column as variant you can use
      ' column letter or number e.g. "A" or 1, "D" or 4 ...
      Const cVntCol As Variant = "A"    ' Column
    
      Dim objRngT As Range              ' Target Range
    
      Dim lngLast As Long               ' Last Row
      Dim lngRows As Long               ' Number of Rows
      Dim lngFirst As Long              ' First Row
    
      With ThisWorkbook.Worksheets("Sheet1")
    
        ' Finding first row and number of rows is easy.
        lngFirst = .UsedRange.Row
            Debug.Print "lngFirst  = " & lngFirst
        lngRows = .UsedRange.Rows.Count
            Debug.Print "lngRows   = " & lngRows
    
        ' Note1: Only when there is data in the first row, the number of rows
        '        is equal to the last row.
    
        ' Therefore we have to calculate the last row.
        lngLast = lngRows + lngFirst - 1
            Debug.Print "lngLast   = " & lngLast
    
        ' Now imagine you have the first data in row 2, and you have 3 rows
        ' which would mean the last data is in row 4 (rows 2, 3, 4). So when you add
        ' 2 + 3 = 5, you have to subtract 1 row, because you counted row 2 twice.
    
        ' Note2: If there is data in the first row then lngFirst = 1.
        '        So the formula will calculate:
        '          lnglast = lngRows + 1 - 1
        '          lngLast = lngRows + 0
        '         which proves the statement in Note1.
    
        ' The previous three lines could have been written in one line:
        lngLast = .UsedRange.Rows.Count + .UsedRange.Row - 1
            Debug.Print "lngLast   = " & lngLast & " (One Row Version)"
    
        ' Now we have all the ingredients for the Target Range.
        Set objRngT = .Cells(lngLast, cVntCol)
            Debug.Print "objRngT   = " & objRngT.Address _
                & " (Before Check if Empty)"
    
        ' And again all this could have been written in one line:
        Set objRngT = .Cells(.UsedRange.Rows.Count + .UsedRange.Row - 1, cVntCol)
            Debug.Print "objRngT   = " & objRngT.Address & " (One Row Version)" _
                 & " (Before Check if Empty)"
        ' then you wouldn't need variables lngLast, lngFirst and lngRows. On the
        ' other hand you wouldn't have learned how this big formula was created.
    
        ' Now the problem is that if the worksheet is empty, UsedRange will show
        ' the cell in the first row as the used range. So we have to address this
        ' issue by checking if all of the following three conditions are true.
        ' - Check if the resulting cell range is in the first row (1).
        ' - Check if from the end of the first row to the beginning the result
        '   is the first cell (1) (all other cells are empty).
        ' - Check if the cell ("A1") is empty.
        If objRngT.Row = 1 And _
            .Cells(1, Columns.Count).End(xlToLeft).Column = 1 And _
            IsEmpty(.Cells(1, 1)) Then
          Debug.Print "objRngT   = Nothing (Empty Worksheet)"
         Else
          Debug.Print "objRngT   = " & objRngT.Address
        End If
        ' Although this is a working code, we can conclude that we should have done
        ' this checking at the beginning which will be done in the advanced version.
    
      End With
    
      Set objRngT = Nothing
    
    End Sub
    '*******************************************************************************
    
  • 0

    上次使用的行和指定列交点专长 .

    查找方法

    我会称之为 safest 和最优雅的方式:使用 Find 方法 .

    '*******************************************************************************
    ' Purpose:    Using the Find method, creates a reference to the cell range at  *
    '             the intersection of the last used row and a specified column     *
    '             in a worksheet and prints its address to the Immediate window.   *
    '*******************************************************************************
    Sub LastUR_Column_Find()
    
      Const cVntCol As Variant = "A"  ' Column Letter or Number ("A" or 1)
      Dim objRngT As Range            ' Target Range
    
      With ThisWorkbook.Worksheets("Sheet1")
        If Not .Cells.Find("*", .Cells(.Rows.Count, .Columns.Count), -4123, , 1) _
            Is Nothing Then
          Set objRngT = .Cells(.Cells.Find("*", , , , , 2).Row, cVntCol)
          Debug.Print "objRngT = " & objRngT.Address
          Set objRngT = Nothing
         Else
          Debug.Print "objRngT = Nothing (Empty Worksheet)"
        End If
      End With
    
    End Sub
    '*******************************************************************************
    ' Remarks:    If you carefully study the "Find method as it applies to         *
    '             the Range object." from "Visual Basic Help", you will realize    *
    '             why exactly those four arguments and their parameters in         *
    '             the If statement must be included and why three of them can      *
    '             be omitted, but a new one has to be added in the Else clause.    *
    '*******************************************************************************
    
  • 0

    如果我已经正确理解,你想找到某个范围(或一堆列)的最后一行 .

    实现此目的的一种方法可能是循环遍历范围内的每一列,找到最后一个单元格(在该特定列中)的哪一行,并检查它是否超过循环中迄今为止最大的最后一行 .

    在下面的代码中,如果您将 "Sheet1" 更改为调用工作表的任何内容,并将范围从 "A4:Z5" 更改为类似 "A:Z""A1:D4" (或您的情况下的任何内容),则应显示您所在的单元格的地址后 .

    Option Explicit
    
    Private Sub ShowLastCell()
        ' Change this to what your sheet is called.
        With ThisWorkbook.Worksheets("Sheet1")
    
            ' Change this to the range you need to check.
            With .Range("A4:Z5")
                Dim firstColumnToCheck As Long
                firstColumnToCheck = .Columns(1).Column
    
                Dim lastColumnToCheck As Long
                lastColumnToCheck = .Columns(.Columns.Count).Column
            End With
    
            Dim maxLastRow As Long
            Dim columnIndex As Long
    
            For columnIndex = firstColumnToCheck To lastColumnToCheck
                maxLastRow = Application.Max(maxLastRow, .Cells(.Rows.Count, columnIndex).End(xlUp).Row)
            Next columnIndex
    
            MsgBox ("I think the cell you want is " & .Cells(maxLastRow, "A").Address & ":" & .Cells(maxLastRow, "A").Address)
    
        End With
    End Sub
    
  • 0

    GetFirstCellInLastLine 将返回引用工作表的最后一行中的第一个单元格作为Range对象 . 然后你可以用它做你想做的事 . 例如,打印到活动工作表的立即窗口:

    Debug.Print GetFirstCellInLastLine(ActiveSheet).Address
    

    如果工作表为空,则设置为返回Noting,但您可以根据需要进行修改:

    '''
    ''' Returns the first used cell in the last line of the worksheet.
    ''' Returns "Nothing" if the worksheet is blank.
    '''
    Public Function GetFirstCellInLastLine(ws As Excel.Worksheet) As Excel.Range
    
    Dim rng As Excel.Range
    
        Set rng = ws.UsedRange.Cells(ws.UsedRange.Rows.Count, 1)
    
        If ((ws.UsedRange.Columns.Count > 1) And ws.Range(rng, rng.End(xlToRight)).Columns.Count <= ws.UsedRange.Columns.Count) Then
            Set rng = ws.Range(rng, rng.End(xlToRight))
            If VBA.IsEmpty(rng.Cells(1, 1)) Then
                Set rng = rng.Cells(1, rng.Columns.Count)
            Else
                Set rng = rng.Cells(1, 1)
            End If
        ElseIf (ws.UsedRange.Columns.Count = 1) And VBA.IsEmpty(rng.Cells(1, 1)) Then
            Set rng = Nothing
        End If
    
        Set GetFirstCellInLastLine = rng
    
    End Function
    

相关问题