【问题标题】:Excel VBA - If statement returning false returns #valueExcel VBA - 如果返回 false 的语句返回 #value
【发布时间】:2017-05-12 16:30:22
【问题描述】:

我正在开发一个更大的 Excel 宏,但我稍微简化了我的代码并发现了我的问题所在。在下面的 if 语句中,我可以将 rng 更改为使语句为真的单元格,并且它工作正常。但是,如果我将其更改为将返回 false 的单元格(或范围内的单元格),它将返回 #value 错误。我对 VBA 很陌生,所以我做错了什么?

Function count_same(column As Range, row As Range)

Dim rng As Range
Dim cell As Range
Dim result As Long
result = 0

Set rng = Worksheets("Install together 2").Range("f10")

For Each cell In rng.Cells

If WorksheetFunction.IsNumber(WorksheetFunction.Search(row.Value, cell.Value)) Then
    result = result + 1
End If

Next cell

count_same = result

End Function

【问题讨论】:

  • 你能提供一个工作和不工作的例子吗,一个单元格是一个范围对象。
  • 上面的工作正常,因为单元格 f10 包含我正在搜索的匹配项。但是,如果我将该范围更改为 f11,甚至是“f10:f11”,它会抛出 #value,因为 f11 不包含我正在搜索的内容。如果它不包含文本,我希望它跳过 f11。
  • 试试这个。 if instr(1,cell,row) > 0 then
  • 他为什么需要跳过错误?对于新程序员来说,这将是非常糟糕的建议。除非绝对必要,否则应避免使用On Error Resume Next
  • 来自 MSDN,关于 SEARCH 方法:“如果找不到 find_text,则返回 #VALUE! 错误值。”您可能必须将其包装在 IfError 方法中才能获得所需的内容,或者以不同的方式重写。你能改写你想用这个实现的目标吗?

标签: vba excel


【解决方案1】:

尝试这样的事情,而不是我以前的答案。如果我正确理解您的需求,这应该可以解决问题。它需要一个输入范围(您要搜索的范围)和一个带有搜索值的输入范围。然后它返回输入范围内该子字符串的实例。

在代码的顶部,我包含了 Application.Volatile,它会在工作表更改时强制它重新计算。您可以将其注释掉。

Function count_same(InputRange As Range, RowValue As Range, ColValue as Range)
    Application.Volatile

    Dim result As Long
    result = 0

    Dim cell As Range
    For Each cell In InputRange.Cells
        If InStr(1, RowValue.Value, cell.Value, vbTextCompare) > 0 And InStr(1, ColValue.Value, cell.Value, vbTextCompare) > 0 Then
            result = result + 1
        End If
    Next cell

    count_same = result
End Function

【讨论】:

  • @thuetten 让我知道上面的代码是否适用于此。如果我理解正确,上面的代码应该可以根据需要工作。
  • 这正是我所需要的。将来我会更多地研究 VBA 函数,而不是强制它使用工作表函数。非常感谢您的所有帮助!
  • 没问题。一旦掌握了 VBA,它就很容易学习。到处玩,看看你能想出什么。你会惊讶于你能做什么:)。
【解决方案2】:

试试这样的:

Function count_same(column As Range, row As Range)

Dim rng As Range
Dim cell As Range
Dim result As Long
result = 0

Set rng = Worksheets("Install together 2").Range("f10")

For Each cell In rng.Cells
    If Not IsError(WorksheetFunction.Search(Row.Value, cell.Value)) Then
        If WorksheetFunction.IsNumber(WorksheetFunction.Search(row.Value, cell.Value)) Then
            result = result + 1
        End If
    End If

Next cell

count_same = result

End Function

从中学习的做法是,我们可以预测潜在的错误。然后我们要做的是检查 IsError 函数的逆函数。如果是错误,IsError 将返回 TRUE。如果它不是错误,我们只想运行 Worksheet 函数。通过If Not IsError,我们实际上是在说“如果这不是错误,那么”。

在您学习 VBA 时,尽量避免出现错误,而不是使用 On Error Resume NextGoTo,因为这些在您刚开始时工作得很好,但在您深入了解时就无法使用(而且您将每次看到 GoTo 或 On Error 语句时都会诅咒自己)。

【讨论】:

  • 因此,对于“f11”范围,它不应该找到匹配项,它应该返回 0。但是如果我把它改回“f10”,它应该找到一个匹配并返回 1,它也返回 0。
  • 开个玩笑,我在上面的建议中重新复制了它,它又回到了原来的样子。在应该返回 1 时返回 1,但在应该为 0 时仍然给出 #value。
  • 我很难弄清楚你的代码到底应该做什么。我也刚刚注意到您有用户输入列,但从未使用过。你想完成什么任务?
  • 所以我确实有一个列范围,但是当它不起作用时,我将其取出以简化故障排除。我有一列包含多个名称的单元格,用分号分隔。我的最终目标是查看一个名称与另一个名称出现多少次 - 所以传递一个名称(行)和另一个名称(列),如果它在单元格中找到行名和列名,它会将 1 添加到结果。这只是实现目标的第一步
  • 列范围是您实际要搜索的范围吗?上面代码中的rng在哪里是占位符?
【解决方案3】:

您可以在下一个错误恢复中使用并进行一些错误检查。您也有列作为范围,但不要在方法中使用它,因此您可以将其删除。

Public Function count_same(row As Range)
On Error Resume Next
Dim rng As Range
Dim cell As Range
Dim result As Long
result = 0

Set rng = ThisWorkbook.Sheets("Install together 2").Range("F10")

For Each cell In rng.Cells

    If WorksheetFunction.IsNumber(WorksheetFunction.Search(row.Value, cell.Value)) Then
        If Err.Number <> 0 Then
            Err.Clear
        Else
            result = result + 1
        End If
    End If

Next cell

count_same = result

End Function

【讨论】:

  • 这确实有效,谢谢。而且我确实有一个列范围,但在我进行故障排除并且无法使其正常工作时被删除。
猜你喜欢
  • 1970-01-01
  • 2020-04-28
  • 2017-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-26
  • 2011-05-09
相关资源
最近更新 更多