I have a chunk of code that is searching repeatedly for a given search text. In fact there are three search texts ("Sub ", "Function " and "Property " respectively). I use the same procedure to do the searches, and reset the boundaries of the range I am searching after each search attempt.
What happens is that when I'm searching for "Sub ", or "Function ", the code works exactly as I would have hoped.But when I'm searching for "Property ", it fails, and effectively gets into an infinite loop (not much fun, and a reminder to ALWAYS save any code changes you make, otherwise you might lose them).
I've attached the chunk of code (3 procedures) and also a copy of the debug.print output that is created.
Code:
Sub CodePrintPass1()
' Build a list of Procedures (Sub and Function procedures).
' Make certain that there as a section break before each procedure.
Dim SearchRange As Word.Range
Dim DocEnd As Long
DocEnd = ActiveDocument.Range.End
CurrentProcType = synSUB
Set SearchRange = ActiveDocument.Content
GoToTopOfSource
While Not EndOfSource
' Find the next occurrence of the CurrentProc between the start point and the end of the document
Pass1GetNextProc SearchRange
SearchRange.End = DocEnd
Debug.Print "Next range:", SearchRange.Start, SearchRange.End
Wend
CurrentProcType = synFUNC
Set SearchRange = ActiveDocument.Content
GoToTopOfSource
While Not EndOfSource
Pass1GetNextProc SearchRange
SearchRange.End = DocEnd
Debug.Print "Next range:", SearchRange.Start, SearchRange.End
Wend
CurrentProcType = synPROPERTY
Set SearchRange = ActiveDocument.Content
GoToTopOfSource
While Not EndOfSource
Pass1GetNextProc SearchRange
SearchRange.End = DocEnd
Debug.Print "Next range:", SearchRange.Start, SearchRange.End
Wend
End Sub
Function Pass1GetNextProc(rng As Word.Range) As tProcEntry
' Find the next occurrence of the keyword Sub (followed by a space!)
' Discard instances where the word is the end of a token (ThisSub, for example)
Dim t As tProcEntry
Dim CommentRange As Word.Range
Dim IsComment As Boolean
t.ProcType = "" ' Indicator that t contains no useful data.
With rng.Find
.Text = CurrentProcType
.Forward = True
.Wrap = wdFindStop
Debug.Print "Start", rng.Start, rng.End
.Execute
If .Found Then
Debug.Print "Found ", rng.Start, rng.End, rng.Text
' Now see if we are on a comment line
Set CommentRange = rng.Duplicate
IsComment = Pass1TestForCommentLine(CommentRange)
If IsComment Then
Debug.Print "Comment", rng.Start, rng.End, rng.Text
' This is a comment line, leave return value undefined and move on to the next word
Else
' We have a valid source line. Construct a new tProcType entry
Debug.Print "Valid Source", rng.Start, rng.End, rng.Text
' Use CommentRange to get the number of lines between the start of the document and the current ProcType
Set CommentRange = rng.Duplicate
CommentRange.Start = ActiveDocument.Range.Start
' Move on to the next word, which contains the Name of the current procedure
rng.Collapse wdCollapseEnd
rng.MoveEnd unit:=wdWord, Count:=1
Debug.Print "ProcName", rng.Start, rng.End, rng.Text
With t
.ProcType = Trim(CurrentProcType)
.Name = rng.Text
.StartLine = CommentRange.ComputeStatistics(wdStatisticLines)
Debug.Print .ProcType, rng.Start, , .Name, "Line " & .StartLine
End With
End If
' Collapse the range, then advance by 1 word to get the name of the procedure
rng.Collapse wdCollapseEnd
Debug.Print "Collapse", rng.Start, rng.End
rng.MoveEnd unit:=wdWord, Count:=1
Debug.Print "Move On", rng.Start, rng.End
rng.Collapse wdCollapseEnd
Debug.Print "Next up", rng.Start, rng.End, rng.Text
Else
EndOfSource = True
Debug.Print "EOF!", rng.Start, rng.End
End If
Debug.Print
End With
rng.Select
Pass1GetNextProc = t
End Function
Function Pass1TestForCommentLine(rng As Word.Range) As Boolean
' See if there is a comment character earlier in the line. If so, then this keyword does not
' count as a valid example of CurrentProcType.
Dim ch As String
While ch <> Chr(13) And ch <> "'"
rng.MoveStart unit:=wdCharacter, Count:=-1
ch = Left(rng.Text, 1)
' Debug.Print rng.Start, rng.End, ch, rng.Text
Wend
If ch = "'" Then
Pass1TestForCommentLine = True
Else
Pass1TestForCommentLine = False
End If
End Function
..and here is the debug output:
Code:
Next range: 5463 11702
Start 5463 11702
Found 5496 5500 Sub
Valid Source 5496 5500 Sub
ProcName 5500 5513 BuildProcList
Sub 5500 BuildProcList Line 187
Collapse 5513 5513
Move On 5513 5515
Next up 5515 5515
Next range: 5515 11702
Start 5515 11702
Found 5868 5872 Sub
Valid Source 5868 5872 Sub
ProcName 5872 5891 zTestOpenSourceFIle
Sub 5872 zTestOpenSourceFIle Line 214
Collapse 5891 5891
Move On 5891 5893
Next up 5893 5893
Next range: 5893 11702
Start 5893 11702
Found 11130 11134 Sub
Valid Source 11130 11134 Sub
ProcName 11134 11138 and
Sub 11134 and Line 394
Collapse 11138 11138
Move On 11138 11147
Next up 11147 11147
Next range: 11147 11702
Start 11147 11702
EOF! 11147 11702
Next range: 11147 11702
Start 0 11702
Found 3339 3348 Function
Valid Source 3339 3348 Function
ProcName 3348 3365 GetSourceFileName
Function 3348 GetSourceFileName Line 83
Collapse 3365 3365
Move On 3365 3368
Next up 3368 3368
Next range: 3368 11702
Start 3368 11702
Found 4051 4060 Function
Comment 4051 4060 Function
Collapse 4060 4060
Move On 4060 4070
Next up 4070 4070
Next range: 4070 11702
Start 4070 11702
Found 4360 4369 Function
Valid Source 4360 4369 Function
ProcName 4369 4384 Pass1GetNextSub
Function 4369 Pass1GetNextSub Line 136
Collapse 4384 4384
Move On 4384 4387
Next up 4387 4387
Next range: 4387 11702
Start 4387 11702
Found 4570 4579 Function
Valid Source 4570 4579 Function
ProcName 4579 4599 Pass1GetNextFunction
Function 4579 Pass1GetNextFunction Line 143
Collapse 4599 4599
Move On 4599 4601
Next up 4601 4601
Next range: 4601 11702
Start 4601 11702
Found 4776 4785 Function
Valid Source 4776 4785 Function
ProcName 4785 4805 Pass1GetNextProperty
Function 4785 Pass1GetNextProperty Line 150
Collapse 4805 4805
Move On 4805 4807
Next up 4807 4807
Next range: 4807 11702
Start 4807 11702
Found 5558 5567 Function
Valid Source 5558 5567 Function
ProcName 5567 5580 GetModuleName
Function 5567 GetModuleName Line 193
Collapse 5580 5580
Move On 5580 5583
Next up 5583 5583
Next range: 5583 11702
Start 5583 11702
Found 5636 5645 Function
Valid Source 5636 5645 Function
ProcName 5645 5659 GetVersionDate
Function 5645 GetVersionDate Line 199
Collapse 5659 5659
Move On 5659 5662
Next up 5662 5662
Next range: 5662 11702
Start 5662 11702
Found 5717 5726 Function
Valid Source 5717 5726 Function
ProcName 5726 5742 GetVersionString
Function 5726 GetVersionString Line 205
Collapse 5742 5742
Move On 5742 5745
Next up 5745 5745
Next range: 5745 11702
Start 5745 11702
Found 11138 11147 Function
Valid Source 11138 11147 Function
ProcName 11147 11157 procedures
Function 11147 procedures Line 394
Collapse 11157 11157
Move On 11157 11159
Next up 11159 11159
Next range: 11159 11702
Start 11159 11702
EOF! 11159 11702
Next range: 11159 11702
Start 0 11702
Found 409 418 PROPERTY
Valid Source 409 418 PROPERTY
ProcName 418 420 =
Property 418 = Line 13
Collapse 420 420
Move On 420 421
Next up 421 421
Next range: 421 11702
Start 421 11702
Found 436 445 PROPERTY
Valid Source 436 445 PROPERTY
ProcName 445 447 =
Property 445 = Line 14
Collapse 447 447
Move On 447 448
Next up 448 448
Next range: 448 11702
Start 448 11702
Found 463 472 PROPERTY
Valid Source 463 472 PROPERTY
ProcName 472 474 =
Property 472 = Line 15
Collapse 474 474
Move On 474 475
Next up 475 475
Next range: 475 11702
Start 475 11702
Found 4853 4862 Property
Comment 4853 4862 Property
Collapse 4862 4862
Move On 4862 4863
Next up 4863 4863
Next range: 4863 11702
Start 4863 11702
Found 4936 4945 property
Comment 4936 4945 property
Collapse 4945 4945
Move On 4945 4946
Next up 4946 4946
Next range: 4946 11702
Start 4946 11702
Found 6751 6760 Property
Valid Source 6751 6760 Property
ProcName 6760 6764 Name
Property 6760 Name Line 240
Collapse 6764 6764
Move On 6764 6765
Next up 6765 6765
Next range: 6765 11702
Start 6765 11702
Found 6751 6760 Property
Valid Source 6751 6760 Property
ProcName 6760 6764 Name
Property 6760 Name Line 240
Collapse 6764 6764
Move On 6764 6765
Next up 6765 6765
Next range: 6765 11702
I've also attached the files containing these data, in case that's easier to look at.
My question is, basically, how come the process of moving on to the next word and extending the range to the end of the document works two out of three times, but fails spectacularly on the third time? The Find object actually goes outside the range, and seems to search backwards(even though it is explicitly set to Forward).
Any ideas?
Thanks,
Tony