首发于 VBA学习

【VBA】查找之Find

今天来一起学习一下VBA中的Find方法吧!

如果我们想在单元格区域[a1:gr20000]中查找内容为“罗小黑”的单元格,可以有以下几种方法:

1,利用For循环查找指定内容,代码如下:

Sub FindDemo1()
Dim iRow As Integer
Dim iColum As Integer
Dim time1 As Date
time1 = Time()
For iRow = 1 To Range("a1").End(xlDown).Row
    For iColum = 1 To Range("a1").End(xlToRight).Column
        If Cells(iRow, iColum) = "罗小黑" Then
            GoTo Findx
        End If
    Next iColum
Next iRow
Findx:
MsgBox "总共用时" & DateDiff("s", time1, Time()) & "秒"
End Sub

通过循环行列逐次查找,总共用时13秒,虽然可以找到,但是效率不够高。

2,利用数组查找,代码如下:

Sub FindDemo2()
Dim ArrayName()
Dim i As Integer
Dim j As Integer
Dim time1 As Date
time1 = Time()
ArrayName = Range("a1").CurrentRegion
For i = LBound(ArrayName, 1) To UBound(ArrayName, 1)
    For j = LBound(ArrayName, 2) To UBound(ArrayName, 2)
        If ArrayName(i, j) = "罗小黑" Then
            GoTo Findx
        End If
    Next j
Next i
Findx:
MsgBox "总共用时" & DateDiff("s", time1, Time()) & "秒"
End Sub

将单元格区域赋值给数组,通过循环数组的上下标去查找,总共用时两秒,非常高效。

3,Find方法查找

虽然数组也很快,但是代码还是稍显冗长,运用range对象的Find方法同样可以快速查找到指定内容,并且代码也会干起来简洁很多。

Sub FindDemo3()
Dim r As Range
Dim time1 As Date
time1 = Time()
Set r = [a1:gr20000].Find("罗小黑")
        If Not r Is Nothing Then
            r.Select
        End If        
MsgBox "总共用时" & DateDiff("s", time1, Time()) & "秒"
End Sub

总共用时1秒,代码量也少很多。

其实range的Find方法就是Excel的查找方法,对应的各个参数也是查找对话框中的各个选项,

4,Find方法详解

Find方法的作用
Find方法将在指定的单元格区域中查找包含参数指定数据的单元格。

  • 查找到指定内容时,返回值:Range对象
  • 若未发现相匹配的数据,返回值:Nothing

Find方法的语法
[语法]
<单元格区域>.Find (What,[After],[LookIn],[LookAt],[SearchOrder],[SearchDirection],[MatchCase],[MatchByte],[SearchFormat]

PS:在每次使用Find方法后,参数LookIn、LookAt、SearchOrder、MatchByte的设置将保存。如果下次使用本方法时,不改变或指定这些参数的值,那么该方法将使用保存的值。
在VBA中设置的这些参数将更改“查找与替换”对话框中的设置;同理,更改“查找与替换”对话框中的设置,也将同时更改已保存的值。也就是说,在编写好一段代码后,若在代码中未指定上述参数,可能在初期运行时能满足要求,但若用户在“查找与替换”对话框中更改了这些参数,它们将同时反映到程序代码中,当再次运行代码时,运行结果可能会产生差异或错误。若要避免这个问题,在每次使用时建议明确的设置这些参数。

Find查找示例

查找what变量所代表的值的单元格,并删除该单元格所在的列。

Sub Find_Error()
  Dim rng As Range
  Dim what As String
  what = "Error"
    Set rng = ActiveSheet.UsedRange.Find(what)
    If rng Is Nothing Then
      Exit Do
       Columns(rng.Column).Delete
    End If
End Sub


带格式的查找
在当前工作表单元格中查找字体为"Arial Unicode MS"且颜色为红色的单元格。其中,Application.FindFormat对象允许指定所需要查找的格式,此时Find方法的参数SearchFormat应设置为True。

Sub FindWithFormat()
  With Application.FindFormat.Font
        .Name = "Arial Unicode MS"
        .ColorIndex = 3
  End With
  Cells.Find(what:="", SearchFormat:=True).Activate
End Sub

5. 与Find方法相联系的方法
可以使用FindNext方法和FindPrevious方法进行重复查找。在使用这两个方法之前,必须用Find方法指定所需要查找的数据内容。
FindNext方法
FindNext方法对应于“查找与替换”对话框中的“查找下一个”按钮。可以使用该方法继续执行查找,查找下一个与Find方法中所指定条件的数据相匹配的单元格,返回代表该单元格的Range对象。


语法
<单元格区域>.FindNext(After)


参数说明
参数After,可选。代表所指定的单元格,将从该单元格之后开始进行查找。开始时不查找该位置所在的单元格,直到FindNext方法绕回到该单元格时,才对其内容进行查找。所指定的位置必须是单元格区域中的单个单元格,如果未指定本参数,则将从单元格区域的左上角的单元格之后开始进行查找。


当查找到指定查找区域的末尾时,本方法将环绕至区域的开始继续查找。发生环绕后,为停止查找,可保存第一次找到的单元格地址,然后测试下一个查找到的单元格地址是否与其相同,作为判断查找退出的条件,以避免出现死循环。当然,如果在查找的过程中,将查找到的单元格数据进行了改变,也可不作此判断,如下例所示。

在单元格区域A1:A500中查找值为2的单元格,并将这些单元格的值变为5。

Sub test1()
  Dim c As Range, firstAddress As String
  On Error Resume Next
  With Worksheets(1).Range("a1:a15")
    Set c = .Find(2, LookIn:=xlValues)
    If Not c Is Nothing Then
      firstAddress = c.Address
        c.Value = 5
        Set c = .FindNext(c)
      Loop While Not c Is Nothing And c.Address <> firstAddress
    End If
  End With
End Sub



FindPrevious方法
可以使用该方法继续执行Find方法所进行的查找,查找前一个与Find方法中所指定条件的数据相匹配的单元格,返回代表该单元格的Range对象。


语法
<单元格区域>.FindPrevious(After)


参数说明
参数After,可选。代表所指定的单元格,将从该单元格之前开始进行查找。开始时不查找该位置所在的单元格,直到FindPrevious方法绕回到该单元格时,才对其内容进行查找。所指定的位置必须是单元格区域中的单个单元格,如果未指定本参数,则将从单元格区域的左上角的单元格之前开始进行查找。

6综合示例
示例一:在当前工作表的单元格区域A1:A50中输入数据5和其它的一些数据,然后在VBE编辑器中输入下面的代码。运行后,程序将在单元格A1:A50区域中查找数值5所在的单元格,并在所找到的单元格中画一个蓝色的椭圆。

Sub FindSample1()
  Dim Cell As Range, FirstAddress As String
  With Worksheets(1).Range("A1:A50")
    Set Cell = .Find(5)
    If Not Cell Is Nothing Then
       FirstAddress = Cell.Address
         With Worksheets(1).Ovals.Add(Cell.Left, _
                                      Cell.Top, Cell.Width, _
                                      Cell.Height)
                                 .Interior.Pattern = xlNone
                                 .Border.ColorIndex = 5