2016-06-13 10 views
3

再帰関数で.Find関数を使用して、シート内の行番号を検索しようとしています。 私はFound = .Find....と呼ばれるオブジェクトを設定し、それは素晴らしい作品...少しです。私は1レベルの再帰深度のときにそれを設定し、2レベル深いときに再び設定します。次に、私のコードはパスの終わりを見つけ、1レベル深くまで戻ってくるまでバックアップを開始しますが、Foundオブジェクトは再宣言され、2番目のレベルからその値が保持されません。私の他の変数(ThisRowなど...)は、それらが存在するレベルの値を保持しています、そして、それは私がオブジェクトで見つけたいものです。それは値が次の関数に拡張されないように、そしてより深いレベルで上書きすることができないようにローカルで発見する方法がありますか?参考までに私のコードを見つけることができます。再帰関数での.Findの使用

はここに私の現在のコードされた - 関係ない部分を切り出し:

Public Function FindChildren() 

ThisRow = AnswerRow 'Also declared before function call 

    BeenHereCell = Cells(ThisRow, "O").Address 
    If Range(BeenHereCell).Value = "Yes" Then 
     Exit Function 'That means we've already been there 
    End If 
    Range(BeenHereCell).Value = "Yes" 

    With Worksheets("MasterScore").Range("j1:j50000") 
     Set Found = .Find(NextQuestionID, LookIn:=xlValues) 
     If Not Found Is Nothing Then 
      firstAddress = Found.Address 
      NextCell = Found.Address 
      Do 

       AnswerRow = Range(NextCell).Row 
       FindChildren 'This is where it's recursive. 

       Set Found = .FindNext(Found) 
       NextCell = Found.Address 

      Loop While Not Found Is Nothing And Found.Address <> firstAddress 
     End If 
    End With 
End Function 

を今私は、細胞を活性化することにより、その周り得ているが、それは私のコードがたくさん遅くなります。

Set Found = Worksheets("MasterScore").Range("j1:j50000").Find(NextQuestionID, LookIn:=xlValues) 
If Not Found Is Nothing Then 
    Count = 1 
    Do 
     Columns("J:J").Select 
     FirstFoundRow = Selection.Find(What:=NextQuestionID, After:=ActiveCell, LookIn:= _ 
     xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:= _ 
     xlNext, MatchCase:=False, SearchFormat:=False).Row 
     For i = 1 To Count 
      Selection.FindNext(After:=ActiveCell).Activate 
     Next i 
     AnswerRow = ActiveCell.Row 
     If AnswerRow = FirstFoundRow And Count <> 1 Then Exit Do 

     FindChildren 
     Count = Count + 1 
    Loop 
End If 

この方法では、私は再びオブジェクトの値を設定する必要はありませんが、私はit.FindNextを通じてかなりの数回の反復処理しなければならないとするたびに、それはその行を実行します。現在、私はこれを使用していますその行を起動します。私は本当に好きなものがほしいと思う。

AnswerRow = .Find(nth instance of NextQuestionID).Row 

(私は約50kの行を持っており、数はかなり頻繁に20になりますので、実際には時間がかかります)。

私は何か考えていただければ幸いです!現在、私のコードは動作していますが、完了するまでにはかなりの時間がかかるでしょう。そして、私はある時点でこれをもう一度実行する必要があります!

答えて

0

少しスピードアップする方法を見つけました。私はこれが誰かを助けることができると思うので、私が見つけたことを分かち合います。 これは最善の解決策ではありません(私は他の関数が値を変更しないようにオブジェクトをローカルに宣言することをお勧めしました)が、少なくともこれを使ってループを繰り返すわけではありません。つまり、Do Loop 。

Set Found = Worksheets("MasterScore").Range("j1:j50000").Find(NextQuestionID, LookIn:=xlValues) 
If Not Found Is Nothing Then 
    NextAnswerRange = "j" & 1 & ":" & "j50000" 'The first search will be from the beginning 

    Do 
     Set Found = Worksheets("MasterScore").Range(NextAnswerRange).Find(NextQuestionID, LookIn:=xlValues) 
     NextCell = Found.Address 
     AnswerRow = Range(NextCell).Row 

     NextAnswerRange = "j" & AnswerRow & ":" & "j50000" 
     If LastAnswerRange = NextAnswerRange Then Exit Function 'This would mean we've reached the end. 
     LastAnswerRange = NextAnswerRange 

     FindChildren 
    Loop 
End If 

エンド機能

だから我々は、それは常に即時に次を見つけたので、我々はすでに以前の範囲で、当社の拠点をカバーしてきました知っています。毎回検索の範囲を変更するだけで、次の値を見つけることができます。

この解決策の奇妙なことは、範囲70-> 50,000の範囲内の値を探していて、行70で探している答えがあれば、実際に次の行が見つかることです)。答えを持っている70過去の任意の行が存在しない場合でも、それは実際にはいくつかの値を逃すので、私は

NextAnswerRange = "j" & AnswerRow + 1 & ":" & "j50000" 

を行うことができなかったことを意味し、行70からの値を取ります。 + 1を使わないで行うと、最後の同じ値を繰り返し検索することになります(Found Is Nothingに戻ることはありません)ので、LastAnswerRange = NextAnswerRange。

私はこれが誰かを助けてくれることを願っています。私はそれが最もエレガントな解決策だとは思わないが、それは私が持っていたよりもはるかに速い。