【问题标题】:Making a CountRows function in Excel在 Excel 中创建 CountRows 函数
【发布时间】:2018-01-05 14:34:18
【问题描述】:

我正在尝试制作一个简单的countRows 函数来计算我在动态范围内拥有的单元格数量。基本上,如果我在单元格中有值,例如 B2:B500,则计数将返回 499。但是,下次值在单元格 B2:B501 中时,计数将返回 500。但是您不必对单元格中的单元格做任何事情您在公式中输入的。

我想如果我将单元格引用为Variant,那么任何值都可以接受。然后找到该单元格的Address 并返回RangeCount。但我收到#Value 错误。

Public Function countRows(startRange As Variant)

    Dim rng As Range
    Set rng = startRange.Address


    If IsEmpty(Range(rng, rng.End(xlDown))) = True Then
        countRows = 1
    Else
        countRows = Range(rng, rng.End(xlDown)).Rows.Count
    End If

End Function

【问题讨论】:

  • 能不能描述的更详细些?
  • Range.Address 返回一个字符串。 set rng = startRange.Address 会抛出错误使用 Set rng = startRange
  • 如果您要假设 startRange 是一个范围,那么您应该将其类型转换为一个范围而不是一个变体。 rng 变量对您的代码没有任何作用。你应该消除它。
  • =COUNTA(B:B)-1?
  • @YowE3K 我相信 OP 正在尝试从头开始创建一些东西。只是说。

标签: vba function count range excel-udf


【解决方案1】:

这是我多年来在许多不同工作表下成功使用的代码。它可以处理许多单元格、单个单元格或空单元格。

Public Function CountRows(ByRef r As Range) As Long
    If IsEmpty(r) Then
        CountRows = 0
    ElseIf IsEmpty(r.Offset(1, 0)) Then
        CountRows = 1
    Else
        CountRows = r.Worksheet.Range(r, r.End(xlDown)).Rows.count
    End If
End Function

Public Function CountCols(ByRef r As Range) As Long
    If IsEmpty(r) Then
        CountCols = 0
    ElseIf IsEmpty(r.Offset(0, 1)) Then
        CountCols = 1
    Else
        CountCols = r.Worksheet.Range(r, r.End(xlToRight)).Columns.count
    End If
End Function

【讨论】:

  • 编辑:函数返回应该是一个 32 位整数(Long 类型)
  • 注意:许多其他实现都包含一个裸露的Range() 对象,它等同于ActiveSheet.Range(),这可能是不受欢迎的行为。上面的代码设计为与工作表无关。
【解决方案2】:

当您提到单元格“B2:B500”中有值并且计数应返回 499 时,您要查找的内容并不完全清楚,因为可能存在以下几种情况:

  • 您只想计算“B2:B500”范围内的行数。代码将是:
  • Range("B2:B500").Rows.Count
    

  • 您想计算“B2:B500”范围内的非空白单元格。在这种情况下,按照 cmets 的建议:
  • WorksheetFunction.CountA(Range("B2:B500"))
    

  • 如代码rng.End(xlDown) 中所示,您可能希望在整个范围“B2:B500”中计算以范围“B2”开始的连续非空白单元格。你可以像这样创建一个函数:
  • Public Function countRows(rng As Range) As Long
        Dim rw As Range
        For Each rw In rng
            If IsEmpty(rw) Then Exit For
            countRows = countRows + 1
        Next
    End Function
    

    澄清

    根据后续的 cmets,我认为有必要通过添加一行 countRows = 0 来解释为什么变量“countRows”没有被初始化。

    某些编程语言(如汇编语言、C、C++)需要显式初始化。之所以如此设计,是因为性能与安全之间的冲突通常以有利于性能的方式解决。

    但是,其他编程语言(如 VBA 或 Java)并非如此。

    说到VBA,在宏运行期间,所有变量都被初始化为一个值。数值变量初始化为零,可变长度字符串初始化为零长度字符串 (""),固定长度字符串用 ASCII 码 0 填充。变体变量初始化为 Empty。空变量在数字上下文中由零表示,在字符串上下文中由零长度字符串 ("") 表示。

    因此,上述代码块中没有添加单独的代码行countRows = 0

    在编码时,需要注意这一点,因为其他语言可能并非如此。

    【讨论】:

    • 另外,countRows 在使用前从未初始化。
    • 嗨,ja72,您可能没有测试代码 n,因此假设“代码非常慢”,即使所有行都有数据(在当前的 excel 版本中最多可能有 1048576 行),它几乎不需要第二个数。在您的第二个点上,请注意Public Function countRows(rng As Range) As Long 行。 Long 的 VBA 默认值为 0,因此不需要 countRows = 0
    • 对于可能需要多次调用CountRows() 的代码,延迟加起来。我不明白为什么不使用End(xlDown)。我认为依赖编译器默认值是不好的。即使C# 要求默认值为零,编译器也会强制在使用前设置一个值。
    • 我实际上是从 End(xlDown) 开始的,但结果是不必要的长 n 因此选择了短的 n sweet For Each 循环,因为性能没有明显差异。顺便说一句,我看了你的帖子 wch 很好,只需要一些改进就可以使它在极端情况下没有错误。注册您对初始化的关注,我在答案中添加了我的解释
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-12
    • 2017-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 2021-12-23
    相关资源
    最近更新 更多