Sub CodePrintPass1()
' Build a list of Procedures (Sub, Function and Property procedures).
' Make certain that there as a section break before each procedure.
Dim SearchRange As Word.Range
Dim DocEnd As Long
' Capture the end of the document we are searching. This value will be used to
' reset the search range.
DocEnd = ActiveDocument.Range.End
RepeatCount = 0
OldRangeStart = 0
' Set the value we are searching for.
CurrentProcType = "document"
' Initial search range is the whole document. Establish the value of the SourcePtr
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
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
Dim StartPos As Long
Dim LineNumber As Long
' Initialize the ProcEntry, which captures information about this procedure.
t.ProcType = "" ' Indicator that t contains no useful data.
' Set up the Find function for this range
With rng.Find
.Text = CurrentProcType ' Use the current search value
.Forward = True ' Always search forward
.Wrap = wdFindStop ' Stop when we get to the end (THIS IS NOT WORKING!)
Debug.Print "Start", rng.Start, rng.End ' Capture the starting information
.Execute
If .Found Then
' A successful find resets the range to the found value. Capture the location
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
StartPos = rng.Start
' 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
LineNumber = CommentRange.ComputeStatistics(wdStatisticLines)
' Move on to the next word, which contains the Name of the current procedure
' This returns to the main range. Collapse it to its end point
rng.Collapse wdCollapseEnd
' Now move the end point on to include the next word (the procedure name), and report that name
rng.MoveEnd unit:=wdWord, Count:=1
Debug.Print "ProcName", rng.Start, rng.End, rng.Text
' Now capture the data about the procedure, and stash it away in t - the ProcType entry
With t
.ProcType = Trim(CurrentProcType)
.Name = rng.Text
.StartLine = LineNumber
.StartPos = StartPos
Debug.Print .ProcType, .StartPos, , .Name, "Line " & .StartLine
End With
End If
' Collapse the range, then advance by 1 word to get the start of the next search
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
' Code to force a stop after 5 badfinds!
If rng.Start = OldRangeStart Then
RepeatCount = RepeatCount + 1
If RepeatCount = 5 Then
EndOfSource = True
End If
Else
OldRangeStart = rng.Start
RepeatCount = 0
End If
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
ch = Left(rng.Text, 1)
Debug.Print , , , rng.Start, ch
While ch <> Chr(13) And ch <> Chr(10) And ch <> "'" And rng.Start > 0
rng.MoveStart unit:=wdCharacter, Count:=-1
ch = Left(rng.Text, 1)
' Debug.Print , , , rng.Start, ch, Asc(ch)
Wend
If ch = "'" Then
Pass1TestForCommentLine = True
Else
Pass1TestForCommentLine = False
End If
End Function
I'd appreciate any comments or suggestions. It's easy enough to program a way around this, but it seems like a heavy burden to pay, given that the documentation makes no reference the phenomenom.
Bookmarks