2017-06-27 8 views
1

私は大まかにフォーマットされたデータセットを扱います。私は必要なデータポイントを取得するために複数のFindメソッドを使用しています。私のサンプルデータベースには、3つのデータ期間(すべて1枚のシート)があり、複数の役員名があります。名前は特定の期間内である場合とそうでない場合があります。私は変数officerSearchを使用して、次のFindメソッドのアンカーポイントとなるアドレスを格納しています。役人の名前が特定の期間内にない場合は、私のFindメソッドはコースから降ります。私のコードコメントの詳細。Excel-VBAシートの最後の後に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メソッドは、私のループが探している期間内に配置されない場合があり、したがって、他のすべてを投げオフ。私はこれをどのように説明するのか困惑しています。

+0

*あなたのコードの '.Find'メソッドのスコープが' Worksheet.Cells'、つまり**ワークシート全体**です。 2番目、3番目、4番目の 'Find'呼び出しの検索範囲を定義するより良い方法が必要です。なぜなら、現在書かれているように、2番目の' .Find'は、あなたの期間の最初のインスタンスを全体から検索しますその下のワークシート。 –

+0

データは日付でソートされていますか? –

+0

http://www.siddharthrout.com/2011/07/14/find-and-findnext-in-excel-vba/ –

答えて

1

戻りRangeオブジェクトとして.Findの結果、むしろ(すなわち、値が見つからない)が存在しないことがあり、オブジェクトにメソッド/プロパティ(例えば、.Address)を連鎖より、Nothing -nessを確認。

officerSearchに再キャストすることもできますが、さまざまな変数名を使用することをお勧めします。混乱させる可能性がありますし、変数も安いです。

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. まず、私たちはあなたのCDate(k)値とdataRangeで初期見つかっ範囲としてsearchRangeを定義します。
  2. これはに基づいて、この日付のいくつのインスタンス 値dataRangeに存在します。
    • 我々は、これは後続のすべての呼び出しのため.Find方法、我々は特定の日付期間(k)に、それを制限しているその方法の親としてsearchRangeをリサイズ使用します。
  3. 次に、担当者の名前が見つかりました。
    • 役人の名前が見つからない場合は、おそらく他に何かしたいことがあります。今すぐプレースホルダーMsgBoxがあります。
  4. 役員名が見つかりました。であれば、我々は総貸付金および延滞が対応する範囲変数(それぞれgrossLoanspastDue)にそれぞれを割り当て、範囲を見つけます。

注:コードはテストされていないため、誤植や間違った括弧などが含まれている可能性があります。特にsearchRange.CurrentRegionは信頼できない可能性があります。ループ外の関連データを含むセルの範囲を定義できると良いでしょう。

+0

ありがとうございます。これはうまくいったようです。ソリューションから1回変更してコードを再作成しました。私はいくつかの書式設定のマジックを行うことができたので、各ステートメント期間は単一の 'currentregion'だったので、' Resize'や 'CountA'を使う必要はなく' Set SearchRange = SearchRange.CurrentRegion'を使いました。 – GoldStandard

+0

@GoldStandardこれは、連続したデータがない場合、つまりデータの各「セット」が1つ以上の空の行で区切られている場合にはおそらく機能します。空の行がない連続したデータテーブルの場合、 'CurrentRegion'はおそらくうまくいかないでしょう:)このコードをあなたの解決策に合わせて調整してください!! –

関連する問題