问题: vba Range.FindNext v Range.Find - 我错过了什么?
您好
(我仍然不太熟悉在这里发帖,如果我有任何不太正确的话,请道歉)
我一直在做一些VBA代码,这些代码都是搜索长列的所有变体。 (通常它涉及连续查找多个事件,要么生成所有事件的列表,要么选择一个或多个(当执行LookAt部件类型选项时))
我不是电脑或编码专业人士,没有那么多经验,所以我错过了什么? ...
我在期待.FindNext的一些优势,与使用.Find进行那种我做过的事情相比。
举一个简单的例子,我想在其中找到带有rOh的两个单词
/ A B C
1
2
3 rOh3
4
5
6
7 rOh7
8
9
10
所以我想要
的Debug.Print输出 rOh3
rOh7
这是我见过的典型代码,也就是我在互联网和教程中找到的代码:
Sub VBAFindNext()
Dim FirstrngFnd As Range, rngFnd As Range
Set FirstrngFnd = Range("B1:B10").Find(What:="roh", LookAt:=xlPart)
If FirstrngFnd Is Nothing Then Exit Sub
Set rngFnd = FirstrngFnd
Debug.Print FirstrngFnd.Value
Do
Set rngFnd = Range("B1:B10").FindNext(rngFnd)
If Not rngFnd = FirstrngFnd Then Debug.Print rngFnd.Value
Loop While Not rngFnd = FirstrngFnd
End Sub
我正在做这样的代码,看起来更简单,更灵活......
Sub FindTheNext()
Dim rngFnd As Range
Set rngFnd = Range("B1:B10").Find(What:="roh", LookAt:=xlPart)
If rngFnd Is Nothing Then Exit Sub
Do While Not rngFnd Is Nothing
Debug.Print rngFnd.Value
Set rngFnd = Range("B" & rngFnd.Row + 1 & ":B10").Find(What:="roh", LookAt:=xlPart)
Loop
End Sub
所以我只是想知道我是否遗漏了什么? 我可以将后面的代码写成这样,但我没有看到任何改进
Sub TheNextVBAFindNext()
Dim rngFnd As Range
Set rngFnd = Range("B1:B10").Find(What:="roh", LookAt:=xlPart)
If rngFnd Is Nothing Then Exit Sub
Do While Not rngFnd Is Nothing
Debug.Print rngFnd.Value
Set rngFnd = Range("B" & rngFnd.Row + 1 & ":B10").FindNext(rngFnd.Offset(1, 0))
Loop
End Sub
所以问题是: 我希望有更多经验的人或更深入了解这些事情的人可以解释任何可能使第一个代码更可取的原因。在我的无知中,我可能会遗漏一些重要的东西。 我想具体问题是“.FindNext的重点是什么”。它只是保存了再次输入搜索条件,或者还有更多的东西。 我想,可能是天真的,对于一个很长的专栏,我的代码可能会更好一点,因为它每次都在缩短的范围内看起来......但是,这是否真实将取决于我猜测“幕后发生了什么” “,我不知道。还有其他人知道吗?如果可能的话,他们可以用简单的方式解释吗。
感谢
艾伦
P.S。我读过有些人认为FindNext被打破了。但我还没有看到任何难以证明的细节。
https://msdn.microsoft.com/de-de/vba/excel-vba/articles/range-findnext-method-excel https://msdn.microsoft.com/de-de/vba/excel-vba/articles/range-find-method-excel .FindNext failing after a .Find function (excel vba)
我所拥有的实际代码通常要复杂得多,这就是为什么我想要了解更多内容: https://www.excelforum.com/excel-programming-vba-macros/1186516-smarter-search-process.html#post4664009
答案 0 :(得分:1)
好的,我现在明白你的意思了。从我的角度来看:
查找:此方法允许您使用您定义的参数开始搜索。每次调用Find
时,您都会创建一个新的搜索过程。
FINDNEXT:此方法将继续使用之前的Find
方法开始搜索,从而节省了再次输入参数的时间,并更新了要搜索的范围(实际上,在第二个和第三个代码您使用Range("B" & rngFnd.Row + 1 & ":B10")
更新搜索范围。使用FindNext
,搜索范围始终相同(在您的示例中为B1:B10
),但VBA会记住最后一个位置并从最后一个位置继续搜索。
那有什么意义呢?好吧,除非设置断点,否则这两种方法都会创建一个无限循环。在第一个代码中,断点位于行Loop While Not rngFnd = FirstrngFnd
中。 VBA会记住搜索到的第一个范围以及何时再循环到此范围内,然后它会中断循环并恢复代码。你的第二个和第三个代码是无限循环。他们永远不会停止执行。试试吧。
如果在第二个和第三个代码中设置了类似的断点,它们将无法工作,因为您要一直更新要搜索的范围,因此无法在使用条件找到的第一个范围内进行搜索,它将是一个无限循环(实际上,无限循环将永远在B10:b10
中搜索。)
要设置有效断点,您需要两种方法。为什么?因为正如我在帖子的开头说的那样,Find
每次调用它时都会启动一个新的搜索,所以它不会移动,你将再次创建一个无限循环。要确保您的搜索转到符合定义条件的下一个范围,您需要使用FindNext
。
我希望这个答案可以为您提供两种方法如何协同工作的线索。无论如何,你可以在这里阅读更多相关信息:
答案 1 :(得分:0)
我认为这是我在答案中最接近的答案。
_1)如果您使用FindNext,则不需要再次提供搜索条件这一事实可能不是特别重要。
_ 2事实上,对于FindNext某地,VBA正在记住最后找到的单元格可能不是特别有利。如果您使用.Find代替我在下面的代码中所做的方式,那么您将实现相同的目标,并且参数中的额外文本可能有助于跟踪代码中正在执行的操作。
_3)我怀疑FindNext可能是一些尝试帮助我不像我在我的代码中那样陷入陷阱(我的第一篇文章中的第二篇......):在进一步的实验中,我发现这两个代码都没有实际上做我想做的事。
例如,如果这是我的测试范围:_...
/ A B C
1 rOh1
2 rOh2
3 rOh3
4
5
6
7 rOh7
8 rOh8
9 rOh9
10
_ ..然后我的代码输出(我的第一篇文章中的第二个)是
rOh2
rOh7
rOh9
问题在于,我编写的代码不会让我从我的范围中的第一个单元格开始 - .Find被编写为如果我没有指定After:=参数,它会开始查看左上角。
如果我确实指定了After:=参数,那么它必须在搜索范围内。所以我不能在调整后的搜索范围之前指定After:=。其实我可以:),有点:
我的下一个代码开展业务。只需始终启动After:=范围内的最后一个单元格。 - 正如Foxfire和伯恩斯和伯恩斯提醒我们的那样,.Find(和.FindNext)继续前进 - 当他们到达搜索范围的末尾时,他们又开始了。通过指定After:=最后一个单元格,搜索始终从搜索范围中的第一个单元格开始。在我的代码中,搜索范围更新到刚刚找到最后一个单元格后的范围。
值得注意的是,传统代码(我给出的第一个代码)虽然运行良好,但对于我在本文中给出的测试数据范围,它将提供以下内容:
rOh2
rOh3
rOh7
rOh8
rOh9
rOh1
你看到它最后找到了“第一场比赛”。我希望如果你不知道这可能会引起一些混乱。
所以我修改后的简化代码似乎对我来说是最好的。它给出了
的输出 rOh1
rOh2
rOh3
rOh7
rOh8
rOh9
这里是代码,注意最后一个单元格应为空
Sub FindTheNext2()
Dim rngFnd As Range
Set rngFnd = Range("B1:B10").Find(What:="roh", after:=Range("B10"), LookAt:=xlPart)
If rngFnd Is Nothing Then Exit Sub
Do While Not rngFnd Is Nothing
Debug.Print rngFnd.Value ' Do anything you wanna do http://www.youtuberepeater.com/watch?v=8GoN-y9irn4&name=Eddie+and+the+Hot+Rods+Do+anything+you+wanna
Set rngFnd = Range("B" & rngFnd.Row + 1 & ":B10").Find(What:="roh", after:=Range("B10"), LookAt:=xlPart)
Loop
End Sub
如果可能使用最后一个单元格,则此代码将处理:
Sub FindTheNext3()
Dim rngFnd As Range
Set rngFnd = Range("B1:B10").Find(What:="roh", after:=Range("B10"), LookAt:=xlPart)
Do While Not rngFnd Is Nothing
Debug.Print rngFnd.Value ' Do anything you wanna do http://www.youtuberepeater.com/watch?v=8GoN-y9irn4&name=Eddie+and+the+Hot+Rods+Do+anything+you+wanna
If rngFnd = Range("B10") Then Exit Sub
Set rngFnd = Range("B" & rngFnd.Row + 1 & ":B10").Find(What:="roh", after:=Range("B10"), LookAt:=xlPart)
Loop
End Sub
如果有更深层次的技术理由为什么Findnext可能是有利的,那么我怀疑任何人都记得。
我的底线我认为是不要打扰它,我不能认为它有很多价值
问题:...... VBA Range.FindNext v Range.Find - 我错过了什么?
答案:...... 没什么,FindNext是浪费时间的混乱。只需使用.Find并确保您确切知道它是如何工作的。