获取实际使用范围

Posted

技术标签:

【中文标题】获取实际使用范围【英文标题】:Getting the actual usedrange 【发布时间】:2011-09-14 21:09:29 【问题描述】:

我有一个带有按钮的 Excel 工作表。

当我调用 usedRange() 函数时,它返回的范围包括按钮部分。

反正我可以得到包含数据的实际使用范围吗?

【问题讨论】:

【参考方案1】:

什么样的按钮,窗体控件和 ActiveX 控件都不应该影响使用的范围。

excel 不能很好地跟踪使用的范围是一个已知问题。通过 VBA 对使用范围的任何引用都会将该值重置为当前使用的范围。所以尝试运行这个子过程:

Sub ResetUsedRng()
    Application.ActiveSheet.UsedRange 
End Sub 

如果你可能有一些格式悬而​​未决。尝试清除/删除最后一行之后的所有单元格。

关于以上内容另见:

Excel Developer Tip

另一种查找最后使用的单元格的方法:

    Dim rLastCell As Range

    Set rLastCell = ActiveSheet.Cells.Find(What:="*", After:=.Cells(1, 1), LookIn:=xlFormulas, LookAt:= _
    xlPart, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False)

更改搜索方向以查找第一个使用的单元格。

【讨论】:

我会试试这个。我最终编写了自己的搜索功能。基本上,如果我找到一个空单元格,我会计算下一个 100 行。如果总数为 0,我认为它是最后一行。 在调用Find之前,请确保您有ActiveSheet.AutoFilterMode=False,否则将不会考虑某些具有实际内容的行。 没有。 Sheet.UsedRange 不能可靠地重置它。它有时会出错并一直出错。 Excel 2007 似乎确实有所改善。 ...但仍然可能出错,特别是如果有数据透视表。 至少在 Excel 2016 中,.Find 命令在用于 .Cells 范围时会跳过合并的单元格,不幸的是,当它们位于已用范围的边界时。【参考方案2】:

Readify 给出了非常完整的答案。但是,我想添加End 语句,您可以使用:

在列中的空白之前查找最后使用的单元格:

Sub LastCellBeforeBlankInColumn()
Range("A1").End(xldown).Select
End Sub

在列中查找最后使用的单元格:

Sub LastCellInColumn()
Range("A" & Rows.Count).End(xlup).Select
End Sub

查找行中空白之前的最后一个单元格:

Sub LastCellBeforeBlankInRow()
Range("A1").End(xlToRight).Select
End Sub

查找一行中最后使用的单元格:

Sub LastCellInRow()
Range("IV1").End(xlToLeft).Select
End Sub

请参阅here 了解更多信息(以及为什么xlCellTypeLastCell 不太可靠的解释)。

【讨论】:

+1 很棒的信息。我建议使用 Range("A" & Rows.Count).End(xlup) 这样您的代码对于多个版本的 excel 都是可行的。【参考方案3】:

根据上述 Reafidy 的解决方案,这是一对返回工作表的最后一行和最后一行的函数。

    Function LastRow(ws As Object) As Long

        Dim rLastCell As Object
        On Error GoTo ErrHan
        Set rLastCell = ws.Cells.Find("*", ws.Cells(1, 1), , , xlByRows, _
                                      xlPrevious)
        LastRow = rLastCell.Row

    ErrExit:
        Exit Function

    ErrHan:
        MsgBox "Error " & Err.Number & ": " & Err.Description, _
               vbExclamation, "LastRow()"
        Resume ErrExit

    End Function

    Function LastCol(ws As Object) As Long

        Dim rLastCell As Object
        On Error GoTo ErrHan
        Set rLastCell = ws.Cells.Find("*", ws.Cells(1, 1), , , xlByColumns, _
                                      xlPrevious)
        LastCol = rLastCell.Column

    ErrExit:
        Exit Function

    ErrHan:
        MsgBox "Error " & Err.Number & ": " & Err.Description, _
               vbExclamation, "LastRow()"
        Resume ErrExit

    End Function

【讨论】:

非常好。我使用了二进制搜索,但这更简单,应该更快。但是,您可能还想指定 Lookin:=xlFormulas;公式可能会返回 "" 其实不是,""匹配"*",和isempty()不同。【参考方案4】:
Public Sub FindTrueUsedRange(RowLast As Long, ColLast As Long)
    Application.EnableEvents = False
    Application.ScreenUpdating = False
    RowLast = 0
    ColLast = 0
    ActiveSheet.UsedRange.Select
    Cells(1, 1).Activate
    Selection.End(xlDown).Select
    Selection.End(xlDown).Select
    On Error GoTo -1: On Error GoTo Quit
    Cells.Find(What:="*", LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Activate
    On Error GoTo -1: On Error GoTo 0
    RowLast = Selection.Row
    Cells(1, 1).Activate
    Selection.End(xlToRight).Select
    Selection.End(xlToRight).Select
    Cells.Find(What:="*", LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Activate
    ColLast = Selection.Column
Quit:
    Application.ScreenUpdating = True
    Application.EnableEvents = True
    On Error GoTo -1: On Error GoTo 0
End Sub

【讨论】:

【参考方案5】:

此函数将实际使用的范围返回到右下限。如果工作表为空,则返回“Nothing”。

'2020-01-26
Function fUsedRange() As Range
Dim lngLastRow As Long
Dim lngLastCol As Long
Dim rngLastCell As Range
    On Error Resume Next
    Set rngLastCell = ActiveSheet.Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious)
    If rngLastCell Is Nothing Then  'look for data backwards in rows
        Set fUsedRange = Nothing
        Exit Function
    Else
        lngLastRow = rngLastCell.Row
    End If
    Set rngLastCell = ActiveSheet.Cells.Find("*", searchorder:=xlByColumns, searchdirection:=xlPrevious)
    If rngLastCell Is Nothing Then  'look for data backwards in columns
        Set fUsedRange = Nothing
        Exit Function
    Else
        lngLastCol = rngLastCell.Column
    End If
    Set fUsedRange = ActiveSheet.Range(Cells(1, 1), Cells(lngLastRow, lngLastCol))  'set up range
End Function

【讨论】:

【参考方案6】:

我使用以下 vba 代码来确定工作表的整个使用行范围,然后缩短列的选定范围:

    Set rUsedRowRange = Selection.Worksheet.UsedRange.Columns( _
    Selection.Column - Selection.Worksheet.UsedRange.Column + 1)

反之亦然:

    Set rUsedColumnRange = Selection.Worksheet.UsedRange.Rows( _
    Selection.Row - Selection.Worksheet.UsedRange.Row + 1)

【讨论】:

【参考方案7】:

这个函数给出了使用范围的所有 4 个限制:

Function FindUsedRangeLimits()
    Set Sheet = ActiveSheet
    Sheet.UsedRange.Select

    ' Display the range's rows and columns.
    row_min = Sheet.UsedRange.Row
    row_max = row_min + Sheet.UsedRange.Rows.Count - 1
    col_min = Sheet.UsedRange.Column
    col_max = col_min + Sheet.UsedRange.Columns.Count - 1

    MsgBox "Rows " & row_min & " - " & row_max & vbCrLf & _
           "Columns: " & col_min & " - " & col_max
    LastCellBeforeBlankInColumn = True
End Function

【讨论】:

UsedRange 的定义还包括格式化的单元格,即使它们是空的。大多数时候,我需要将 UsedRange 定义为非空单元格。【参考方案8】:

在 Excel 2013 上的时间相当慢,使用范围非常大,百万行:

26ms Cells.Find xlPrevious 方法(同上)

0.4ms Sheet.UsedRange(随便叫)

0.14ms Counta 二分搜索 + 0.4ms Used Range 开始搜索(12 CountA 调用)

因此,如果担心的话,Find xlPrevious 会很慢。

CountA 二分查找方法是先做一个Used Range。然后将范围切成两半,看看下半部分是否有非空单元格,然后根据需要再次减半。做对是很棘手的。

【讨论】:

【参考方案9】:

这是另一个。它查找第一个和最后一个非空单元格,并且构建范围来自这些单元格。这也可以处理您的数据不是矩形且不是从 A1 开始的情况。此外,它还处理合并的单元格,当从宏执行时,.Find 会跳过这些单元格,用于工作表上的 .Cells。

Function getUsedRange(ByRef sheet As Worksheet) As Range
' finds used range by looking for non empty cells
' works around bug in .Find that skips merged cells
' by starting at with the UsedRange (that may be too big)

' credit to https://contexturesblog.com/archives/2012/03/01/select-actual-used-range-in-excel-sheet/
' for the .Find commands

Dim excelsUsedRange As Range
Dim lastRow As Long
Dim lastCol As Long
Dim lastCell As Range
Dim firstRow As Long
Dim firstCol As Long
Dim firstCell As Range

Set excelsUsedRange = ActiveSheet.UsedRange

lastRow = excelsUsedRange.Find(What:="*", _
                               LookIn:=xlValues, SearchOrder:=xlRows, _
                               SearchDirection:=xlPrevious).Row
lastCol = excelsUsedRange.Find(What:="*", _
                               LookIn:=xlValues, SearchOrder:=xlByColumns, _
                               SearchDirection:=xlPrevious).Column
Set lastCell = sheet.Cells(lastRow, lastCol)

firstRow = excelsUsedRange.Find(What:="*", After:=lastCell, _
                                LookIn:=xlValues, SearchOrder:=xlRows, _
                                SearchDirection:=xlNext).Row
firstCol = excelsUsedRange.Find(What:="*", After:=lastCell, _
                                LookIn:=xlValues, SearchOrder:=xlByColumns, _
                                SearchDirection:=xlNext).Row
Set firstCell = sheet.Cells(firstRow, firstCol)
Set getUsedRange = sheet.Range(firstCell, lastCell)
End Function

【讨论】:

以上是关于获取实际使用范围的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 android 的帐户管理器获取多个范围的身份验证令牌

js获取窗口滚动条高度窗口可视范围高度文档实际内容高度滚动条离浏览器底部的高度

获取表列中序列值的范围

当 Model 超出使用范围时,实际会发生啥?

Random类的概述和基本使用---Java

使用 Apache Solr 进行 Drupal 日期范围索引