If I can say one thing about myself, it's that I'm lazy. I spend all kinds of time writing comments in my programs, but I hate spending time creating documentation describing the apps I've written. I do like to write code, however, so I decided to write a utility to help automate my documentation chores. This month's VBDoc utility extracts and formats comments in your VB6 projects to use as a starting point for your project documentation. Download the sample code. Load and run VBDoc in the VB design environment to see how it works. The default project is VBDoc.vbp itself, or you can click on the Browse button to choose a different VB project. You can see a list of the project's files in the Files in Project listbox. Click on each filename in turn to see the header comments displayed in the Contents area. Header comments include the first contiguous block of comments in the file. If the file includes optional delimiters ('+= and '-= by default), the header comments include the delimiters and all lines in between. You set the desired delimiters with the Tools | Set Delimiters menu item. You can edit and save the header comments in the Contents area without modifying the source files. Click on the Show Docs button to fill the contents area with formatted text. Because the Contents area is a RichTextBox control, VBDoc can use font styles to delimit sections in the documentation output. Project attributes are listed first, followed by the header comments for each file in your project. You click on the Save Docs button to save the documentation to a Rich Text Format (RTF) file you can edit with Word or other applications (see Figure 1). The file defaults to the project name and directory, as in VBDoc.rtf. Set breakpoints at important points in the VBDoc project so you can see how the code operates. Go to the Project Explorer (View | Project Explorer or Ctrl+R) in the VB design environment. Right-click on frmMain and choose View Code from the context menu, or click on the View Code icon at the top of the project window. Set a breakpoint on the first line in frmMain's CreateDocFile routine by clicking in the gray-colored left margin next to the line containing the GetPath call. VB highlights the line of code in red when you set a breakpoint. You also set breakpoints on the first executable lines in the ShowFileDoc and ShowDoc routines, as well as on the first executable lines in clsProject's ProjectFile Property Let procedure and in clsFile's Init method. Start the VBDoc project by pressing the F8 key. F8, the Step-Into function key, starts the program on the first executable line in the startup form's Form_Load event. The yellow highlight represents the next statement to execute. Continue pressing F8, and on the third repetition the debugger steps into the InitSettings routine. Press F8 a couple more times, then use the Step-Out function key (Ctrl+Shift+F8) to continue running the program until you're back at the line in Form_Load following the call to InitSettings. Now use the Step-Over function key (Shift+F8) to continue through the Form_Load routine without seeing each lower-level routine execute. When you step over the line in Form_Load that sets the default project path, VB stops at your breakpoint in the clsProject's ProjectFile Property Let routine:
If InStr(UCase$(ProjectFilename), _
".VBP") Then
You can see how VB arrived at this point by choosing the View | Call Stack menu item (or by pressing Ctrl+L). You can jump into the code at any point in the call stack by double-clicking on a routine name in the list. The line labeled Non-Basic Code indicates that VB fired an event routine on your behalf. Continue from your breakpoint by pressing the Run key (F5), and the debugger then stops at the breakpoint in clsFile's Init method for the first file. For now, continue by pressing the Run key (F5) repeatedlyonce for each file in the projectuntil the main form shows. VBDoc's key element is a pair of class modules, clsProject and clsFile. Restart your project and run it (F5) to the first breakpoint in clsProject's ProjectFile Property Let procedure. Step over each line (Shift+F8) until you reach the LoadFile call. Step into LoadFile (F8) to see how the contents of the VBP file are returned:
Public Function LoadFile _
(ByVal FileName As String) As String
Dim iFileNum As Integer
iFileNum = FreeFile
Open FileName For Input As #iFileNum
LoadFile = Input(LOF(iFileNum), #iFileNum)
Close #iFileNum
End Function
The Input statement reads the number of bytes specified by the Length of File (LOF) function. Use Step-Out (Ctrl+Shift+F8) to return to the ProjectFile routine. Next, step into the ParseProject function to load the project's properties and files (see Listing 1). The process of reading a file and taking apart its contents is called parsing. ParseProject first uses the Split function to separate the VBP file by carriage return-line feed characters using the vbCrLf constant. This is a quick way of breaking the file into individual lines. Individual properties in the VBP file are composed of key-value pairs:
Class=clsProject; CProject.cls
You loop and split each line in the file using the = character to separate each key name from its value, and you pick up individual project properties and filenames with a Case statement. You create an instance of clsFile in ParseProject for each file in the project, and you call the Init property to load and analyze the file:
Case "FORM","MODULE","CLASS"
'project files
If colFiles Is Nothing Then _
Set colFiles = New Collection
Set oFile = New clsFile
oFile.Init sFileType, sFileName, _
GetPath(ProjectFile)
colFiles.Add oFile, oFile.FileName
Set oFile = Nothing
You store each file instance (one for each file in the project) in the colFiles collection using the filenames as collection keys. Continue stepping the debugger or use the Run key (F5) until you come to the breakpoint in the clsFile Init routine, where you collect file attributes and read the file contents using the LoadFile routine:
m_sFileContents = LoadFile _
(GetFilePath(BasePath, m_sFileName))
The GetFilePath function determines the physical path to your project files. You need this function if some of your project's source files come from outside your source directory. This is common in situations where you have a library of common modules, classes, and forms in a common directory that you reuse on projects. If your source files all come from the same directory (as with VBDoc), the GetFilePath function returns the project directory. Continue pressing F5 to run at each breakpoint until the main form shows again. Parse Project Files
Now let's look at how you collect file header comments. Click on a filename in the Files in Project list, and VB stops at your breakpoint in frmMain's ShowFileDoc routine:
Set oFile = goProject.FileRef(FileName)
rtbProjectDoc.Text = oFile.FileHeader
The goProject.FileRef property returns a file object reference from the project's Files collection. Step into the oFile.FileHeader routine to see how VBDoc handles file header analysis:
Public Property Get FileHeader() As String
'returns the File Header comments
If Len(m_sFileHeader) = 0 Then
m_sFileHeader = ParseHeader()
GetLineCount
End If
FileHeader = m_sFileHeader
End Property
If the file header for this file hasn't been processed already, you call the ParseHeader routine to extract the comments (see Listing A). ParseHeader separates the file into individual lines and searches for the header comment block. Header comments are found either between the optional delimiters or as the first contiguous block of comments. Finally, let's see how you create formatted output. Click on the Show Docs button, and VB stops at your breakpoint in frmMain's ShowDoc routine (see Listing B). You format text programmatically in the RichTextBox by selecting the text and applying formatting to the selected text. You use the sFormat array in ShowDoc to keep track of where formatting is required in the output. The sFormat array contains a series of comma-delimited entries that specify the beginning character position in the text, the offset, and a descriptive name for the format ("Heading1", "Heading2"). Step through the code in ShowDoc to see how VBDoc creates the output from the project and file properties. Click on this line near the bottom of ShowDoc:
FormatDoc sFormat
Use the Run to Cursor keyboard shortcut (Ctrl+F8) to run to the selected line. Step into the FormatDoc routine to see how the RichTextBox formatting is applied (see Listing C). Here, you loop through the sFormat array, select the appropriate text, and apply the appropriate font style for the format name. Continue running the app, and click on the Save Docs button to run to your final breakpoint in frmMain's CreateDocFile routine. You create the output file using the SaveFile method of the RichTextBox:
rtbProjectDoc.SaveFile sFile, rtfRTF
And that's it! Try enhancing VBDoc on your own by listing referenced objects (such as OCX files) or all the routine declarations in each file. Use the debugger shortcuts you've learned to debug your new features. Then rest easy knowing your project documentation chores have just gotten easier. Stan Schultes is a project and IT manager and a VB/Web enterprise application architect and developer in Sarasota, Fla. Stan is an MCP in VB and spoke on VB development at Microsoft's DevDays conference. He is a contributing editor for Visual Studio Magazine and writes regularly for it. Reach Stan at stan@vbexpert.com. |