为什么我的电子表格函数的行为与从代码调用时的行为不同?

end*_*and 5 vba spreadsheet user-defined-functions

当我从Excel(在单元格中)调用该函数时:

=allVlookup(O24,A:D,3,"")
Run Code Online (Sandbox Code Playgroud)

vs通过vba

MsgBox allVlookup(Range("O24"), Range("A:D"), 3, "")
Run Code Online (Sandbox Code Playgroud)

我得到了不同的结果.当从Excel调用时,我只获得第一个匹配,但是当从具有相同参数的vba测试子调用时(除了添加Range参数以允许子运行),我得到完整的结果(多于一个).

我正在使用的功能是:

Public Function allVlookup(lookupRange As Range, tableRange As Range, colIndex As Integer, Optional delimiter As String = "") As String

    Dim c As Range
    Dim firstAddress As String
    'MsgBox tableRange.Address  ' this is correct
    'With Sheets(4).Range("A1:C12").Columns(1)
    'With Range("A1:C12").Columns(1)

    'this doesn't allow things to work right either (???)
    'Set tableRange = Range("A:D")
    'Set lookupRange = Range("O24")

    'search only the first column for matches
    With tableRange.Columns(1)
        Set c = .Find(what:=lookupRange.Value, LookIn:=xlValues)

        If Not c Is Nothing Then

            firstAddress = c.Address

            Do
                'add the delimiter
                If (allVlookup <> "") Then
                    allVlookup = allVlookup + delimiter
                End If

                'append value to previous value
                allVlookup = allVlookup + c.Offset(0, colIndex).Value


                Set c = .FindNext(c)
                'exit conditions
                'no match found
                If (c Is Nothing) Then
                    Exit Do
                    'we're back to start
                ElseIf (c.Address = firstAddress) Then
                    Exit Do
                End If

            Loop
        End If
    End With

End Function
Run Code Online (Sandbox Code Playgroud)

我无法解释为什么会这样.

我该怎么做才能使输出相同?

Sid*_*out 2

它只给出第一个匹配的原因是因为一个错误。请参阅底部的链接(第 5 节)。

\n

我很久以前就已经将其作为错误提交了。如果您阅读了上面的链接,那么我也建议了替代代码。

\n

从该链接中提取内容,以防链接失效(它不应该)

\n

.FindNext 无法按预期在用户定义函数中工作。您可以在正常功能中使用它。

\n

假设 Sheet1 中有这些数据:

\n
A1 \xe2\x86\x92 Colt\nA2 \xe2\x86\x92 Holt\nA3 \xe2\x86\x92 Dolt\nA4 \xe2\x86\x92 Hello\n
Run Code Online (Sandbox Code Playgroud)\n

并在

\n
B1 \xe2\x86\x92 olt\n
Run Code Online (Sandbox Code Playgroud)\n

现在,如果我们将以下代码粘贴到模块中并运行它,那么我们将得到预期的结果:$A$1:$A$3

\n
Sub Test()\n    Sample Sheets("Sheet1").Range("B1"), Sheets("Sheet1").Range("A1:A4")\nEnd Sub\n \nSub Sample(FirstRange As Range, ListRange As Range)\n    Dim aCell As Range, bCell As Range, oRange As Range\n    Dim ExitLoop As Boolean\n    Set oRange = ListRange.Find(what:=FirstRange.Value, LookIn:=xlValues, _\n    lookat:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _\n    MatchCase:=False, SearchFormat:=False)\n    ExitLoop = False\n    If Not oRange Is Nothing Then\n        Set bCell = oRange: Set aCell = oRange\n \n        Do While ExitLoop = False\n            Set oRange = ListRange.FindNext(After:=oRange)\n \n            If Not oRange Is Nothing Then\n                If oRange.Address = bCell.Address Then Exit Do\n                Set aCell = Union(aCell, oRange)\n            Else\n                ExitLoop = True\n            End If\n        Loop\n        MsgBox aCell.Address\n    Else\n        MsgBox "Not Found"\n    End If\nEnd Sub\n
Run Code Online (Sandbox Code Playgroud)\n

但是,如果您将此函数粘贴到模块中并从工作表中调用它(例如在单元格 C1 中),它将无法按预期工作=FindRange(A1,A1:A5)

\n

该代码只会为您提供找到的值的第一个实例,并忽略其余的

\n

因此,您将得到的结果是 $A$2!!!

\n
Function FindRange(FirstRange As Range, ListRange As Range) As String\n    Dim aCell As Range, bCell As Range, oRange As Range\n    Dim ExitLoop As Boolean\n    Set oRange = ListRange.Find(what:=FirstRange.Value, LookIn:=xlValues, _\n    lookat:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _\n    MatchCase:=False, SearchFormat:=False)\n    ExitLoop = False\n    If Not oRange Is Nothing Then\n        Set bCell = oRange: Set aCell = oRange\n \n        Do While ExitLoop = False\n            Set oRange = ListRange.FindNext(After:=oRange)\n \n            If Not oRange Is Nothing Then\n                If oRange.Address = bCell.Address Then Exit Do\n                Set aCell = Union(aCell, oRange)\n            Else\n                ExitLoop = True\n            End If\n        Loop\n        FindRange = aCell.Address\n    Else\n        FindRange = "Not Found"\n    End If\nEnd Function\n
Run Code Online (Sandbox Code Playgroud)\n

我们需要从不同的角度来处理这个问题。

\n

我们不再使用 .FindNext,而是再次使用 .Find,直到得到所需的结果($A$1:$A$3)。请参阅下面的代码,该代码有效:

\n
Function FindRange(FirstRange As Range, ListRange As Range) As String\n    Dim aCell As Range, bCell As Range, oRange As Range\n    Dim ExitLoop As Boolean\n    Set oRange = ListRange.Find(what:=FirstRange.Value, LookIn:=xlValues, _\n    lookat:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _\n    MatchCase:=False, SearchFormat:=False)\n    ExitLoop = False\n    If Not oRange Is Nothing Then\n        Set bCell = oRange: Set aCell = oRange\n \n        Do While ExitLoop = False\n            Set oRange = ListRange.Find(what:=FirstRange.Value, After:=oRange, LookIn:=xlValues, _\n            lookat:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _\n            MatchCase:=False, SearchFormat:=False)\n            If Not oRange Is Nothing Then\n                If oRange.Address = bCell.Address Then Exit Do\n                Set aCell = Union(aCell, oRange)\n            Else\n                ExitLoop = True\n            End If\n        Loop\n        FindRange = aCell.Address\n    Else\n        FindRange = "Not Found"\n    End If\nEnd Function\n
Run Code Online (Sandbox Code Playgroud)\n