繁体   English   中英

使用.Find函数VBA-不返回第一个值

[英]Using the .Find Function VBA - not returning the first value

我已经为较大的程序编写了代码摘录,以测试概念验证。 (因此,代码很少。)主代码背后的想法是,用户使用带有复选框的Custom UserForm生成数组,然后在数组中搜索所有提及的“ 1”,即当复选框包含被选中。 然后,使用数组的行号基于所选的复选框来加载一系列额外的用户窗体。 我想象有更简单的方法可以做到这一点,但这是我选择的方法,我在VBA方面的编码经验非常有限!

我已附上了所生成数组的示例。

主代码生成的arrey的测试示例

当我运行代码时,除单元格(1,2)= 1的情况外,它均按预期工作

谁能看出来这是为什么,我已经为此苦苦挣扎了一段时间。

Sub Array_Finder()

    Dim StartFinder As String
    Dim StartFinderZero As String
    Dim StartFinderCheck As String

    i = 4 : j = 1
    StartFinderZero = 0 : StartFinderCheck = i + 2
    For StartFinderTest = 1 To i + 1
        StartFinder = StartFinderZero + 1
        If StartFinderCheck > StartFinder Then
            StartFinderZero = Range(Cells(StartFinder, 2), Cells(i + 1, 2)).Find _
                (What:="1", after:=Cells(StartFinder, 2), searchdirection:=xlNext).Row
            Cells(StartFinderTest, 3) = StartFinderZero
        Else
            MsgBox ("here")
            Exit For
        End If
    Next StartFinderTest
End Sub

使用您的代码:

Sub ArrayFinder()

    Dim StartFinder As Long
    Dim StartFinderZero As String
    Dim StartFinderCheck As String
    i = 4: j = 1
    StartFinderZero = 0: StartFinderCheck = i + 2

    For StartFinderTest = 1 To i + 1
        StartFinder = StartFinderZero + 1
        If StartFinderCheck > StartFinder Then    
            With Range(Cells(StartFinder, 2), Cells(i + 1, 2))
                Debug.Print "row" & vbTab & .Cells(.Cells.Count).Row
                Debug.Print "address" & vbTab & .Address
                Debug.Print "after"; vbTab & .Cells(.Cells.Count).Address
                StartFinderZero = .Find(1, after:=.Cells(.Cells.Count)).Row
            End With    
            Cells(StartFinderTest, 3) = StartFinderZero
        Else
            Debug.Print "here"
            Exit For
        End If
    Next StartFinderTest

End Sub

这是您在立即窗口中看到的:

row 5
address $B$1:$B$5
after    $B$5
row 5
address $B$2:$B$5
after    $B$5

技巧如下( MSDN的After参数):

您要在其之后开始搜索的单元格。 这对应于从用户界面进行搜索时活动单元格的位置。 注意,After必须是该范围内的单个单元格。 请记住,搜索是在此单元格之后开始的; 在方法返回到该单元之前,不搜索指定的单元 如果不指定此参数,则搜索将在范围左上角的单元格之后开始。

因此,您将最后一个单元格作为开始。 它知道它应该之后开始。 因此,从理论上讲,它没有更好的选择,而只是从范围的开头开始。 After参数的想法是设置将要检查的最后一个值。 因此,如果我们只有一个值,则无论After参数如何, 它总是会正确返回 如果有多个值,它将返回找到的第一个值。

因此,在上面的代码中,由于使用了.Find() 之后 ,按以下顺序搜索单元格:

B1> B2> B3> B4> B5

如果没有After,则序列如下:

B2> B3> B4> B5> B1


为了更好地说明,假设您有两个不同的范围,如下所示:

在此处输入图片说明

使用左侧代码,如果您搜索1行,那么即使使用以下代码,即使没有选择after参数,也将始终可以:

Sub TestMe()
    Dim myR     As Range
    Dim myS     As Range
    Set myS = Range("B1:B5") 'change the range
    With myS
        Set myR = .Find(1)
        Debug.Print myR.Row
        Set myR = .Find(1, after:=.Cells(.Cells.Count))
        Debug.Print myR.Row
    End With
End Sub

右边的范围是很微妙的,因为它也有1次。 因此,必须要有after才能从第一个单元格获取值。如果尝试这样做,则会在即时窗口中显示21

这几乎就是为什么我决定在某个时候决定使用一种缓慢的方法,该方法只是在范围内循环并检查值,而不是内置 到LastThings的 .Find() GitHub链接

我认为一切都发生在一张纸上。 它适用于您提供的数据。

Sub MyAnswer()
    Dim lRow As Long ' Number of rows (or last row)
    Dim rngCheckBoxes As Range ' Range of values
    Dim vArr()
    ' Calculate last row
    lRow = ActiveSheet.Range("A" & ActiveSheet.Rows.Count).End(xlUp).Row
    ' Define range of checkboxes' numbers
    Set rngCheckBoxes = ActiveSheet.Range("A1","A" & lRow)
    ' Replace all zeroes with empty string
    rngCheckBoxes.Offset(0,1).Replace "0", "", xlWhole
    ' Put all values from defined range into array
    ' where according values from column next to it aren't blank
    vArr = rngCheckBoxes.Offset(0,1).SpecialCells(xlCellTypeConstants).Offset(0,-1).Value
    ' Insert array values into column "C"
    ActiveSheet.Range("C1").Resize(Ubound(vArr),1).Value = vArr
End Sub

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM