May I Make a Comment?
Microsoft® Word 2000
Summary: The first part of this two-part article, May I Make a Comment? Part I: Adding Comments, described a custom solution for entering comments when certain words appear in your Microsoft Word 2000 documents. The custom solution described in part two of this two-part article allows users to view, edit, and delete the comments of multiple reviewers. (6 printed pages)
In part one of this two-part article, I described the basics of creating comments in Microsoft® Word 2000 using Visual Basic® for Applications. In addition, I provided a custom solution for inserting comments into a document when certain words appeared. This article discusses a second custom solution that allows you to view and edit multiple reviewers' comments.
As mentioned in part one, Microsoft Word 2000 allows users to display only one reviewer's comments or all reviewers' comments. For example, the code shown below uses the ShowBy property of the Comments collection to display one reviewer's comments.
Sub ShowByAuthor() ThisDocument.Comments.ShowBy = "Mark Lee" End Sub
If you wanted to display the comments of all of the reviewers in a document, you would change the ShowBy property to "All Reviewers" or a zero-length string, as follows:
Sub ShowAllAuthors() ThisDocument.Comments.ShowBy = "All Reviewers" End Sub
Note If you enter a name that Word cannot locate among the reviewers in a document (either the name is misspelled or doesn't exist), Word will display all of the comments in the document.
Although you can use the ShowBy property to display the comments of only one author or all authors, the custom solution explained in this article extends Word 2000 by allowing users to review the comments of more than one author. This custom solution is comprised of a UserForm, a custom class module, and a separate code module. With this custom solution, users can select multiple authors to review, edit document and comment text, and delete comments.
To create this solution, you will first need a UserForm similar to the one shown below in Figure 1 (the UserForm is available in the sample download). Name the UserForm frmComments and change the caption text for all controls to match the figure below.
Figure 1. The UserForm
Accept the default settings for all of the controls, except for the controls shown in Table 1 below.
Table 1. UserForm control settings
|CommandButton||(Name) cmdReviewComments |
Caption View Comments
|CommandButton||(Name) cmdClose |
|ListView||(Name) lstAuthors |
Note In order to use this control, you must add it to the Toolbox. To do so, right-click the Toolbox, click Additional Controls, and then select Microsoft List View Control 6.0.
|Label||(Name) lblAuthor |
|Label||(Name) lblIndex |
Caption Comment No.
|CommandButton||(Name) cmdNext |
Caption Next Comment >>
|CommandButton||(Name) cmdPrevious |
Caption << Previous Comment
|CommandButton||(Name) cmdChangeDocText |
Caption Change Document Text
|CommandButton||(Name) cmdChangeComment |
Caption Change Comment Text
|CommandButton||(Name) cmdDeleteComment |
Caption Delete Comment
I used a custom class module (clsSelectedAuthorsComments) to create a collection of comments that consists of comments written only by the authors a user has selected in the ListView control. The class module consists mainly of two functions.
The first function (GetSelectedAuthorsComments) in the class module compiles a custom collection of the selected authors' comments. You can compile the collection of comments of the selected authors in one of two ways.
The first way is by adding the comments of the selected authors to the custom collection in the order in which the comments appear in the document. To accomplish this, the GetSelectedAuthorsComments function first compiles a string of the names of the authors the user has selected in the ListView control, as shown in the following code sample. Next, it loops through each comment in the specified document and uses the Visual Basic InStr function to check if the compiled string contains the comment's author name. If the author's name exists in the string, it adds the comment to the custom collection.
For Each itmList In lst.ListItems If itmList.Checked = True Then _ strAuthorName = strAuthorName & itmList.Text Next itmList For Each cmt In objDocument.Comments If InStr(1, strAuthorName, cmt.Author) > 0 Then _ p_mcolSelectedAuthorsComments.Add Item:=cmt, Key:=CStr(cmt.Index) Next cmt
The second way is to compile the custom collection so that the code adds comments to the collection in the order of the selected authors' names as they appear in the ListView control. To accomplish this, the following code sample first starts a loop through the items in the ListView control and if checked, places the author's name in a string. Next it reviews each comment in the specified document and if the name of the comment's author and the string match, adds the comment to the collection. It continues to loop through each of the checked items in the ListView and compiles the collection by author.
For Each itmList In lst.ListItems If itmList.Checked = True Then strAuthorName = itmList.Text For Each cmt In objDocument.Comments If cmt.Author = strAuthorName Then m_colSelectedAuthors.Add Item:=cmt, Key:=CStr(cmt.Index) End If Next cmt End If Next itmList
Both of the above examples are included in the GetSelectedAuthorsComments function; however, the second example is commented out. You may use either way to create a custom comments collection for a document.
The second function (NextComment) in the class module allows users to move back and forth through the custom collection. The direction in which to move through the custom comments collection is based on the value of the intDirection argument. The intDirection argument requires a custom enumerated type called cmtMove, which is declared as public in the General Declarations section. There are three possible values for cmtMove: cmtMoveFirst, cmtMoveNext, and cmtMovePrevious. CmtMoveFirst moves to the first comment in the custom collection; cmtMoveNext advances one comment unless the active comment is the last comment in the custom collection, in which case it leaves the next comment as the last comment; and cmtMovePrevious moves back one comment in the custom collection unless the active comment is the first comment in the collection, in which case it leaves the next comment as the first comment.
The separate code module (modComments) consists of three subroutines and one function. These subroutines are mostly used for housekeeping for the form and the information displayed on the form.
When first displayed, the user form shows only the left portion of the full form. After a user selects the authors whose comments he or she wants to review and clicks the View Comments button, the full form is displayed. The ResizeForm subroutine toggles the form between its initial reduced size and its full size.
The GetCommentAuthors subroutine populates the ListView control with the names of the comment authors in the document. The DisplayComment subroutine displays the following information for the current comment:
- Document text (Scope)
- Comment text
- Author's name
- Comment's position in the document's Comments collection
The DisplayComment subroutine calls the RemoveFromString function to remove the reference mark from the comment's Scope text before displaying it in the textbox on the form.
Because most of the functionality for this solution is in the class module, there is very little code behind the UserForm. The Initialize event for the UserForm verifies that there are comments in the active document and calls the FormResize and GetCommentAuthors subroutines in the modComments code module.
The Click event for the cmdReviewComments command button calls the DisplayComment and the ResizeForm subroutines in the separate code module. The Click event for the cmdNext and cmdPrevious command buttons also both call the DisplayComment subroutine. For the cmtActive argument of the DisplayComment subroutine, the code for the cmdReviewComments, cmdNext, and cmdPrevious command buttons all specify the active comment using the NextComment function of the class module. The following code from the cmdNext_Click event demonstrates how these three event routines call the DisplayComment subroutine and specify the active comment.
Call DisplayComment(objDocument:=ActiveDocument, _ cmtActive:=clsAuthors.NextComment(intDirection:=cmtMoveNext), _ lblAuthor:=Me.lblAuthorName, lblIndex:=Me.lblIndex, _ txtScope:=Me.txtScope, txtComment:=Me.txtComment)
The only difference between the three event routines is that the code for the cmdReviewComments command button's Click event specifies the intDirection argument as cmtMoveFirst; and the code for the cmdPrevious command button's Click event specifies the intDirection argument as cmtMovePrevious.
The Click event for the lstAuthors ListView control is where most of the action for the UserForm starts. It enables the cmtReviewComments command button and sets the clsComments global variable to the clsSelectedAuthorsComments custom class. However, the routine must destroy the custom class variable if it already exists. This is a critical step because it allows users to add or remove the comments of one or more authors from the custom collection at any point while they are reviewing the selected authors' comments.
The ShowBy method of the Comments collection allows you to filter the comments in Word documents to display only the comments of a single reviewer or all of the reviewers of a document. Now, with the custom solution described in this article, you can create a very useful tool for your users to review the comments of multiple reviewers in their documents.