首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Excel VBA -函数在使用FindNext后停止(工作在子程序中)

Excel VBA -函数在使用FindNext后停止(工作在子程序中)
EN

Stack Overflow用户
提问于 2019-08-27 01:41:33
回答 1查看 310关注 0票数 0

我正在编写一个函数,它将在一个名为“使用”的指定工作表中找到列中的所有单元格,其中将有多个单元格与我所找到的单元格相匹配。问题是,当我试图调用FindNext时,VBA将停止工作而不会抛出任何错误。--但是如果我将函数转换为子例程,它就会非常好地工作,因为Debug显示了找到的所有10个单元格地址。但是我需要使用一个函数,因为我将根据找到的结果返回一个值。在使用FindNext时,在调试行上使用F8后,函数就会停止--至少有10个值与传递的项相匹配。完全不明白为什么它作为子例程而不是函数工作。

代码语言:javascript
运行
复制
Function FindAllCells(item As String) As String

  Dim searchRange As Range
  Dim foundItem As Range
  Dim firstCellAddress As String

  Set searchRange = Sheets("Usage").Range("A:A")
  Set foundItem = searchRange.Find(What:=item, LookAt:=xlWhole)

  If foundItem Is Nothing Then
    Exit Function
  End If

  firstCellAddress = foundItem.Address

  Do 
    Set foundItem = searchRange.FindNext(foundItem)
    Debug.Print foundItem.Address
  Loop While firstCellAddress <> foundItem.Address

  FindAllCells = foundItem.Offset(0,2)
End Function  
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-08-27 03:15:59

今天早些时候,我需要一个UDF,它可以显示单个单元格中的每个匹配项。我记得我编写了一个函数,它可以做到这一点,我回到这里是为了重用我的代码。

不幸的是,对我来说,这是具体的操作问题,不够灵活,以满足我目前的需要。

我的损失就是你的收获!

现在,我已经完全重写了函数,以接受Range.Find中几乎所有的参数。据我所知,像xlByColums这样的Excel枚举器在工作表中不可用。我不可能在短期内记住所有这些参数,所以通过将大多数参数转换为布尔值使事情变得更简单。searchByColumnfindPartialMatchreverseSearchDirectioncaseSensitivelookAtFormat都是通过True/False设置的,但是xlFindLookIn仍然需要常量值来指定注释/公式/值。

这还不是全部..。

输出不一定是匹配的项。它可以是匹配项的地址或偏移量。想象一下,如果VLOOKUPINDEXMATCH将它们匹配的所有内容放入一个单元格中,这基本上就是偏移参数所允许的。对于那些重要的时刻,输出可以包括匹配的总数。

等等,还有更多!

这是一个很小但非常重要的选项,可以通过参数从工作表中设置分隔符。

可以这么说,这个函数可以以多种方式使用,我将不可避免地回来重用它。

请注意,我使用了一个具有两个不同条件退出点的无限循环,逻辑应该清晰易懂,但如果您开始编辑代码,则需要注意。

代码语言:javascript
运行
复制
Public Function FindAllMatches(ByVal searchFor As String, ByVal searchRange As Range, _
                                    Optional ByVal columnOffset As Long, _
                                    Optional ByVal rowOffset As Long, _
                                    Optional ByVal countMatches As Boolean, _
                                    Optional ByVal showAddresses As Boolean, _
                                    Optional ByVal delimiter As String, _
                                    Optional ByVal findPartialMatch As Boolean = True, _
                                    Optional ByVal searchByColumn As Boolean = False, _
                                    Optional ByVal reverseDirection As Boolean = False, _
                                    Optional ByVal caseSensitive As Boolean = False, _
                                    Optional ByVal lookAtFormat As Boolean = False, _
                                    Optional ByVal lookInside As XlFindLookIn = xlValues _
                                    ) As String

    Dim firstMatchCellAddress As String
    Dim searchResult As Range
    Dim returnString As String
    Dim matchCount As Long
    Dim includePartial As Single: includePartial = -findPartialMatch + 1
    Dim previousDirection As Single: previousDirection = -reverseDirection + 1
    Dim searchAxis As Single: searchAxis = -searchByColumn + 1

    If Not CBool(Len(delimiter)) Then delimiter = Chr(44)
    Set searchResult = searchRange

    Do
        Set searchResult = searchRange.Find(What:=searchFor, After:=searchResult.Cells(searchResult.Cells.Count), LookIn:=lookInside, _
                LookAt:=includePartial, SearchOrder:=searchAxis, SearchDirection:=previousDirection, _
                MatchCase:=caseSensitive, SearchFormat:=lookAtFormat)

        Select Case True

            Case searchResult Is Nothing
                Exit Do

            Case firstMatchCellAddress = searchResult.Address
                Exit Do

            Case CBool(Len(returnString))
                If showAddresses Then
                    returnString = returnString & delimiter & searchResult.Offset(rowOffset, columnOffset).Address
                Else
                    returnString = returnString & delimiter & searchResult.Offset(rowOffset, columnOffset)
                End If

            Case Else
                If showAddresses Then
                    returnString = searchResult.Offset(rowOffset, columnOffset).Address
                Else
                    returnString = searchResult.Offset(rowOffset, columnOffset)
                End If

                firstMatchCellAddress = searchResult.Address

        End Select

        matchCount = matchCount + 1

    Loop While True

    If countMatches Then
        If CBool(matchCount) Then
            returnString = matchCount & delimiter & returnString
        Else
            returnString = 0
        End If
    End If

    FindAllMatches = returnString

End Function
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57666720

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档