Excel-VBA如何在工作表结束后停止FIND方法的循环?

时间:2017-06-27 14:56:49

标签: excel-vba vba excel

我有一个粗略格式化的数据集可供使用,我正在使用多个Find方法来获取我需要的数据点。我的示例数据库有三个数据周期(全部在一张纸上),有多个官员名称。名称可能在特定时期内也可能不在。我使用变量officerSearch来存储地址,该地址充当以下Find方法的定位点。除非官员姓名不在特定时期,否则我的Find方法会偏离正常。我的代码评论中有更多细节。

For Each k In dateArray.keys  'loops through my periods. Each key is a unique date
For i = 0 To officerListBox.ListCount - 1 
    If officerListBox.Selected(i) = True Then 'Performs _
          Find methods for each officer selected in list box
        officerSearch = Cells.Find(what:=CDate(k), LookIn:=xlFormulas, _
           searchorder:=xlByRows, searchdirection:=xlNext).Address 'Finds first instance of the first period (k)
        officerSearch = Cells.Find(what:=officerListBox.List(i), _
           after:=Range(officerSearch), LookIn:=xlValues, lookat:=xlWhole, _
           searchorder:=xlByRows, searchdirection:=xlNext).Address _
       'Finds officer name starting after the date cell was found. _
        But if the raw data set doesn't have the officer name in that period, _
        my Find method will find an officer name further on down the sheet _
        (or loop around at the beginning of the sheet) where the name is found in a different period. 
        officerSearch = Cells.Find(what:="Gross Loans", after:=Range(officerSearch), _
           LookIn:=xlValues, lookat:=xlWhole, searchorder:=xlByRows, _
           searchdirection:=xlNext).Address 'Finds the cell labeled Gross Loans starting after an officer name is found
        officerSearch = Cells.Find(what:="Total 30 - 59 days past due", _ 
           after:=Range(officerSearch), LookIn:=xlValues, lookat:=xlWhole, _
           searchorder:=xlByRows, searchdirection:=xlNext).Address 'Finds the cell _
        labeled Total 30-59 days past due starting after _
        an officer name is found.

    End If
    Next i 'Starts the find loop over for the next selected officer name
Next k 'Starts the find loop over for the next period in the dataset

所以我的第一,第三和第四个Find方法保证存在于我期望的位置,但第二个Find方法可能不在我的循环搜索的时间段内,因此抛弃其他所有内容。我很难理解如何解释这一点。

1 个答案:

答案 0 :(得分:2)

.Find的结果作为Range对象返回,并检查Nothing - ness,而不是将方法/属性(例如,.Address)链接到对象可能不存在(即找不到值)。

为不同的事情使用不同的变量名称可能也是一个好主意,当然你可以重新转换为officerSearch,这可能会让人感到困惑和限制,此外,变量很便宜。 / p>

理想情况下,您希望定义一个您关注的表或一系列单元格,而不是以Cells.Find开头,然后将其用作.Find的基础,而不是调用该方法针对整个工作表。这是您需要定义的dataRange对象。

Dim dataRange As Range '## range containing ALL data
Set data Range = Range(...) '## MODIFY AS NEEDED
Dim searchRange as Range, offName as Range, grossLoans as Range, pastDue as Range
'## Finds first instance of the first period (k) in the worksheet.Cells
Set searchRange = dataRange.Find(what:=CDate(k), LookIn:=xlFormulas, searchorder:=xlByRows, searchdirection:=xlNext) 

'## Define the range of cells containing this (k) period:
'    Assumes the (k) date is only present in one column
Set searchRange = searchRange.Resize(Application.WorksheetFunction.CountA(dataRange, CDate(k))

'## Finds officer name ONLY WITHIN THE searchRange, defined above
Set offName = searchRange.Find(what:=officerListBox.List(i), after:=Range(officerSearch.Cells(1).Address), LookIn:=xlValues, lookat:=xlWhole, searchorder:=xlByRows, searchdirection:=xlNext)  

'## Get out of here if the value isn't found
If offName Is Nothing Then
    ' you probably want a GoTo or Exit For statement here...
    MsgBox "Not found!"
Else
    '## Otherwise, find Gross Loans beneath Officer Name:
    Set grossLoans = searchRange.Find(what:="Gross Loans", after:=Range(offName.Address), LookIn:=xlValues, lookat:=xlWhole, searchorder:=xlByRows, searchdirection:=xlNext) 
    Set pastDue = searchRange.Find(what:="Total 30 - 59 days past due", after:=Range(grossLoans.Address), LookIn:=xlValues, lookat:=xlWhole, searchorder:=xlByRows, searchdirection:=xlNext) 
End If

工作原理:

  1. 首先,我们使用您的searchRange值将dataRange定义为CDate(k)中的初始找到范围。
  2. 然后我们Resize这基于该日期的实例数 价值存在于dataRange中。
    • 我们将使用此已调整大小的searchRange作为所有后续调用的.Find方法的父级,这样我们就可以将其限制为特定日期(k)。
  3. 然后我们找到了军官的名字。
    • 如果找不到官员姓名,您可能想要做其他事情,现在有一个占位符MsgBox
  4. 如果发现人员姓名 ,那么我们会找到总贷款和过期费用范围,并将每个人分配给相应的范围变量(grossLoanspastDue)。< / LI>

    注意:代码未经过测试,可能包含错别字,错位的括号等。特别是searchRange.CurrentRegion可能不可靠,如果您可以定义范围更好包含循环外相关数据的单元格。