【问题标题】:Better way to find last used row找到最后使用的行的更好方法
【发布时间】:2016-12-17 08:44:05
【问题描述】:

我正在尝试以与找到最后一列相同的方式找到最后一行:

Sheets("Sheet2").Cells(1,Sheets("Sheet2").Columns.Count).End(xlToLeft).Column

我知道这种方式,但它不像以前那样有用:

u = Sheets("Sheet1").Range("A65536").End(xlUp).Row

我试过了:

Sheets("Sheet2").Cells(Sheets("Sheet2",1).Rowa.Count).End(xlToUP).Column

简介:我希望最后一行的方式如下。

Sheets("Sheet2").Cells(1,Sheets("Sheet2").Columns.Count).End(xlToLeft).Column

【问题讨论】:

  • 为什么不使用Sheets("Sheet2").UsedRange.Rows.Count
  • 但本质上是Sheets("Sheet2").Cells(1,Sheets("Sheet2").Rows.Count).End(xlUp).Row
  • 我正在使用一个改变的 for 循环,所以我想要单元格格式。更改范围对我来说很困难,而拥有一个单元格要容易得多。
  • 它返回这个,“运行时错误'1004'。

标签: excel vba


【解决方案1】:

您应该使用 with 语句来限定您的 RowsColumns 计数。这将防止在使用旧的 2007 之前和更新的 2007 Excel 工作簿时出现任何错误。

最后一栏

With Sheets("Sheet2")
    .Cells(1, .Columns.Count).End(xlToLeft).Column
End With 

最后一行

With Sheets("Sheet2")
    .Range("A" & .Rows.Count).End(xlUp).Row
End With 

或者

With Sheets("Sheet2")
    .Cells(.Rows.Count, 1).End(xlUp).Row
End With 

【讨论】:

  • 对于查找最后一行的两种方法都不起作用。我不断收到“运行时错误'438':对象不支持此属性或方法”。
  • 这段代码在一张空白纸上返回“1”,这怎么可能?如果里面没有值,我希望它返回。
  • @smartini 因为此方法返回一行(无论是否为空),如果该行包含值,则在最后返回该行。 2 种可能性:检查 A1 = vbnullstring 或使用 find 方法
  • 三个都错了。如果最后一列被填满,第一个将返回错误值,如果最后一行被填满,其他两个将返回错误值。
【解决方案2】:

这是怎么回事?

dim rownum as integer
dim colnum as integer
dim lstrow as integer
dim lstcol as integer
dim r as range

'finds the last row

lastrow = ActiveSheet.UsedRange.Rows.Count

'finds the last column

lastcol = ActiveSheet.UsedRange.Columns.Count

'sets the range

set r = range(cells(rownum,colnum), cells(lstrow,lstcol))

【讨论】:

    【解决方案3】:

    如果你想指定一个特定的工作表,这个函数应该可以解决问题。我从 user6432984 那里得到了解决方案,并对其进行了修改以不抛出任何错误。我使用的是 Excel 2016,因此它可能不适用于旧版本:

    Function findLastRow(ByVal inputSheet As Worksheet) As Integer
        findLastRow = inputSheet.cellS(inputSheet.Rows.Count, 1).End(xlUp).Row
    End Function
    

    如果您已经在工作表中要查找最后一行,则这是要运行的代码:

    Dim lastRow as Integer
    lastRow = cellS(Rows.Count, 1).End(xlUp).Row
    

    【讨论】:

      【解决方案4】:

      我使用此例程来查找数据行数。所需的开销最小,但通过使用递减的比例进行计数,即使是非常大的结果也需要很少的迭代。例如,28,395 的结果只需要 2 + 8 + 3 + 9 + 5 或 27 次循环,而不是耗时的 28,395 次。

      即使我们将其乘以 10 (283,950),迭代次数也是相同的 27 次。

      Dim lWorksheetRecordCountScaler as Long
      Dim lWorksheetRecordCount as Long
      
      Const sDataColumn = "A"   '<----Set to column that has data in all rows (Code, ID, etc.)
      
          'Count the data records
          lWorksheetRecordCountScaler = 100000  'Begin by counting in 100,000-record bites
          lWorksheetRecordCount = lWorksheetRecordCountScaler
      
          While lWorksheetRecordCountScaler >= 1
      
              While Sheets("Sheet2").Range(sDataColumn & lWorksheetRecordCount + 2).Formula > " "
                  lWorksheetRecordCount = lWorksheetRecordCount + lWorksheetRecordCountScaler
              Wend
      
              'To the beginning of the previous bite, count 1/10th of the scale from there
              lWorksheetRecordCount = lWorksheetRecordCount - lWorksheetRecordCountScaler
              lWorksheetRecordCountScaler = lWorksheetRecordCountScaler / 10
      
          Wend
      
          lWorksheetRecordCount = lWorksheetRecordCount + 1   'Final answer
      

      【讨论】:

        【解决方案5】:

        这将为您提供指定列中最后使用的行。

        您可以选择指定工作表,否则它将采用活动工作表。

        Function getLastRow(col As Integer, Optional ws As Worksheet) As Long
        
            If ws Is Nothing Then Set ws = ActiveSheet
            
            If ws.Cells(ws.Rows.Count, col).Value <> "" Then
                getLastRow = ws.Cells(ws.Rows.Count, col).Row
                Exit Function
            End If
        
            getLastRow = ws.Cells(Rows.Count, col).End(xlUp).Row
        
            If shtRowCount = 1 Then
                If ws.Cells(1, col) = "" Then
                    getLastRow = 0
                Else
                    getLastRow = 1
                End If
            End If
        
        End Function
        
        Sub test()
        
            Dim lgLastRow As Long
            lgLastRow = getLastRow(2) 'Column B
        
        End Sub
        

        【讨论】:

          【解决方案6】:

          这是我见过的找到最后一个单元格的最佳方法。

          MsgBox ActiveSheet.UsedRage.SpecialCells(xlCellTypeLastCell).Row
          

          使用它的一个缺点是它并不总是准确的。如果您使用它然后删除最后几行并再次使用它,它并不总是更新。不过,在使用它之前保存您的工作簿似乎会强制它更新。

          在更新表(或刷新提供表的查询)之后使用下一段代码会强制在找到最后一行之前更新所有内容。但是,据报道它会使excel崩溃。无论哪种方式,在尝试查找最后一行之前调用它都将确保表首先完成更新。

          Application.CalculateUntilAsyncQueriesDone
          

          另一种获取任何给定列的最后一行的方法,如果您不介意开销的话。

          Function GetLastRow(col, row)
              ' col and row are where we will start.
              ' We will find the last row for the given column.
              Do Until ActiveSheet.Cells(row, col) = ""
                  row = row + 1
              Loop
              GetLastRow = row
          End Function
          

          【讨论】:

          • 由于您给出的原因,我不得不不同意您的观点。我发现针对特定列/行的 xlUp/xlLeft 方法或针对工作表上最后一个单元格的 Find("*") 是最可靠的方法。
          • @DarrenBartrup-Cook 我无法让接受答案中的代码为我工作。但是我发布的代码对我来说效果很好。
          • @DarrenBartrup-Cook Find 方法有效,但是如果所有行都是 vbnullstring 并且 .End(xlUp).Row 返回最后一行不为空或列的第一个单元格,您需要测试结果是否为空
          • @MatthewGoheen 这个答案是最简单的。只要列中间没有空白单元格,它就可以工作。最后一行应该是 GetLastRow = row - 1 ?
          【解决方案7】:

          普通方法的问题

          空白行/列的帐户 - 如果您的数据开头有空白行或列,则 UsedRange.Rows.Count 和 UsedRange.Columns.Count 等方法将跳过这些空白行(尽管它们确实考虑了可能破坏数据的任何空白行/列),因此如果您参考 ThisWorkbook.Sheets(1).UsedRange.Rows.Count 在工作表顶部有空白行的情况下(例如在此工作表上),您将跳过行:

          这将从计数中跳过第一行并返回 11:

          ThisWorkbook.Sheets(1).UsedRange.Rows.Count
          

          此代码将包含空白行并返回 12:

          ThisWorkbook.Sheets(1).UsedRange.Cells(ThisWorkbook.Sheets(1).UsedRange.Rows.Count, 1).Row
          

          同样的问题也适用于列。

          全张 - 如果您的工作表已满,则识别最后一行或最后一列可能会很困难(这仅在您的数据包含超过一百万行或数据的最后一行或列中可能有值时才重要)。例如,如果您使用 xlEndUp 或类似方法并且您所指的单元格已填充,则代码将跳过数据,在极端情况下,如果数据从工作表的最后一行继续,则可以跳过您的整个数据集(您开始 xlEndUp 的位置)一直到第一行(在这种情况下,结果将为 1)。

          'This code works, but... 
          'Will not function as intended if there is data in the cell you start with (Cell A:1048576).
          Dim Sht1 as Range: Set Sht1 = ThisWorkbook.Sheets(1)
          Sht1.Cells(Sht1.Rows.Count, 1).End(xlUp).Row
          

          带有空白行的列 - 上面的代码还假设您的数据一直延伸到第 1 列,如果您在第 1 列中有空白条目,您可能会丢失行,因为代码会从底部找到第一个填充的行 only 1.

          不必要的循环 - 不言自明,最好尽可能避免循环,就好像您正在处理大量数据并经常重复循环过程会减慢您的代码。

          解决方案

          请注意,这旨在查找整个工作表上的最后一个“已使用”行或列,如果您只希望特定范围内的最后一个单元格,这将不起作用。

          我在这里设置了一些函数

          Private Function GetLastRow(Sheet As Worksheet)
          'Gets last used row # on sheet.
          GetLastRow = Sheet.UsedRange.Cells(Sheet.UsedRange.Rows.Count, 1).Row
          End Function
          
          Private Function GetLastCol(Sheet As Worksheet)
          'Gets last used column # on sheet.
          GetLastCol = Sheet.UsedRange.Cells(1, Sheet.UsedRange.Columns.Count).Column
          End Function
          

          调用这些函数的示例:

          Sub CallFunctions()
              'Define the Target Worksheet  we're interested in:
              Dim Sht1 As Worksheet: Set Sht1 = ThisWorkbook.Sheets(1)
              'Print the last row and column numbers:
              Debug.Print "Last Row = "; GetLastRow(Sht1)
              Debug.Print "Last Col = "; GetLastCol(Sht1)
          End Sub
          

          【讨论】:

            【解决方案8】:

            我更喜欢搜索最后一个空白单元格:

            如果你想要列的最后一个空单元格,你可以这样做

            Dim sh as Worksheet, r as range
            set sh = ActiveWorksheet 'if you want an other it's possible
            
            'find a value 
            'Columns("A:D") 'to check on multiple columns 
            Set r = sh.Columns("A").Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious)
            'no value return first row
            If r Is Nothing Then Set r = sh.Cells(1, "A") Else Set r = sh1.Cells(r.Row + 1, "A")
            

            如果这是插入新行,在多列上查找是一个不错的选择,因为第一列可以包含比下一列更少的行

            【讨论】:

              【解决方案9】:

              我广泛使用以下功能。如上所述,由于使用的范围更新、数据中的间隙或具有不同行数的不同列,使用其他方法有时会得出不准确的结果。

              使用示例:

              lastRow=FindRange("Sheet1","A1:A1000")
              

              将返回整个范围内最后占用的行号。您可以指定从单列到随机行的任何范围,例如 FindRange("Sheet1","A100:A150")

              Public Function FindRange(inSheet As String, inRange As String) As Long
                  Set fr = ThisWorkbook.Sheets(inSheet).Range(inRange).find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious)
                  If Not fr Is Nothing Then FindRange = fr.row Else FindRange = 0
              End Function
              

              【讨论】:

                猜你喜欢
                • 2023-03-28
                • 2012-03-24
                • 2013-10-16
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-06-18
                • 1970-01-01
                相关资源
                最近更新 更多