Excel Vba方法Range.Find

时间:2016-01-23 16:58:32

标签: excel vba excel-vba methods

我遇到了问题,Range.Find方法应该为它做好工作,

在Microsoft网站(Rang.Find Method)上,找到了我认为需要的代码:

Set C = wsCountry.Range("G:G").Find(What:="BOSS", MatchCase:=True, LookAt:=xlWhole, LookIn:=xlValues, SearchDirection:=xlNext, SearchOrder:=xlByRows)
    If Not C Is Nothing Then
        firstAddress = C.Address
            Do
               If wsRep.Range("B:B").Find(What:=C.Offset(0, -5), LookIn:=xlValues) Is Nothing Then
                    wsUser.Range("SpecialPO").Find(What:="BOSS", MatchCase:=True, LookIn:=xlValues).Offset(0, 1) = wsUser.Range("SpecialPO").Find(What:="BOSS", MatchCase:=True, LookIn:=xlValues).Offset(0, 1) + 1
                End If
                Set C = wsCountry.Range("G:G").FindNext(C)

                If C Is Nothing Then Exit Do
                Loop While C.Address <> firstAddress
    End If

问题:

当尝试使用.FindNext第二次设置变量C时,它将抛出值&#34; Nothing&#34;。虽然该列还有另外两个值为&#34; BOSS&#34;

(我发现了一个范围内容,我可能会使用siddharthrout在Section 3中建议的其他解决方案。虽然我想知道为什么这个解决方案没有按预期工作)

一如既往,非常感谢。

1 个答案:

答案 0 :(得分:0)

回答原始问题

问题:

  

以下行导致错误。

Loop While Not C Is Nothing And C.Address <> firstAddress
     

错误:未设置对象变量或块变量。

在VBA中,If / While等评估复合条件的所有部分(和,或),与例如C ++ - 即,在VBA中,And和Or不会短路。因此,首次检查Is Nothing是否会导致对成员的第二次检查无法执行,因此变量未设置错误。

因此,解决方案是在通过嵌套的If检查任何成员之前单独测试Is Nothing。这不能在While中完成,因此需要在While循环结束之前单独完成,并且您应该将结果存储在变量中以在While中进行测试。

即使您发布的代码来自MSDN,它仍然可能是错误的:)

要查看此操作,请在VBA模块中运行以下代码:

Sub x()
  Dim o As Range
  Set o = Nothing
  Do While Not o Is Nothing And o.Address = "whatever"
    Call MsgBox("Made it!")
  Loop
End Sub

回答更新的问题

当你在一个范围上调用.Find时,你会创建一个查找上下文。这就是.FindNext知道接下来要找什么的方法。当你中断&#39;一个Find / FindNext序列与第二个(无关的).Find(在一个不相关的范围,例如),你搞乱这个上下文。下次要在原始范围上继续.FindNext时,上下文将无法使用,.FindNext将开始返回错误的结果。请注意,.Find并不是一个很好用的功能;它实际上会更改用户的“查找”对话框中的默认值。这也暗示了Excel中只有一个查找上下文,它与用户操作的GUI共享(不好,但你能做什么)。

请参阅以下代码了解其工作原理。选择一个空白纸,填写如下:

Column A  Column B
a         d
b         e
c         f
a         d
b         e
c         f

然后运行下面的代码;它会告诉你&#34;没有找到下一个&#34;。现在注释掉第二个.Find on oSearchRangeB并再次运行它;它现在返回&#34; FindNext&#34;。

Sub x()
  Dim oSearchRangeA As Range
  Set oSearchRangeA = ActiveSheet.Range("A:A")
  Dim oSearchRangeB As Range
  Set oSearchRangeB = ActiveSheet.Range("B:B")
  Dim oFoundCell As Range
  Set oFoundCell = oSearchRangeA.Find( _
    What:="b", MatchCase:=True, LookAt:=xlWhole, LookIn:=xlValues, _
    SearchDirection:=xlNext, SearchOrder:=xlByRows _
  )
  If Not oFoundCell Is Nothing Then
    Dim oInterferingFoundCell As Range
    Set oInterferingFoundCell = _
      oSearchRangeB.Find(What:="f", LookIn:=xlValues)
    Set oFoundCell = oSearchRangeA.FindNext(oFoundCell)
    If oFoundCell Is Nothing Then
      Call MsgBox("Didn't FindNext")
    Else
      Call MsgBox("Did FindNext")
    End If
  End If
End Sub