Techniques - DevSource
DevSource: Microsoft Developer Resource DevSource Home Sponsored by Microsoft Home Add Ons Architecture Languages Techniques Using VS Forums
Home arrow Techniques arrow Cleaning Up with VBA
Cleaning Up with VBA
By John Mueller

Rate This Article: Add This Article To:

Collaborative editing makes writing documents within a workgroup easier, but then you have to clean up the mess of highlights and edits. Visual Basic for Applications can help make the job easier.

Many companies use collaboration tools to create documentation that reflects the knowledge and abilities of a team, often in a short timeframe. Everyone works with a single document, marking it up with their personal highlighting, notes, and edits. Unfortunately, the resulting mess can be difficult to clean up, especially if you want to retain some of the edits, accept others, and delete still others. Performing the task by hand isn't impossible, but it's time consuming and may be error prone. Unfortunately, without a carefully created macro, using automation might destroy the very information you want to keep.

Fortunately, Microsoft Office provides great programmatic access to edits on a page. All you need to know is what to look for and what you want as output from the automation.

ADVERTISEMENT

There's three steps. First, consider what to do with all the highlights. (Some might be important, so deleting all of them isn't a good idea. Second, decide what to do with the actual edits. You may decide to accept all the edits, or perform the task manually; but in some cases, you can use a reviewer's name or other flag to determine whether to remove, leave, or accept the edit. Third, if your company uses the Word annotation feature, you need to clean up the annotations you no longer need.

Removing Unneeded Highlights

If the document's authors don't use Word's revision marking, they need to mark "whose text is whose" in some other way. Typically, each author uses a different color. To remove the highlights that are no longer necessary, we expect each member of the collaborative team to use a separate color, or for each kind of highlight in the document to be color-highlighted. Unless the color has a specific meaning, you can't remove it using automation, which means you'll send a lot of time deciding whether to keep the highlight manually.

Deciding on an editing technique at the outset saves a lot of time. Listing 1 demonstrates how to locate and remove a particular highlight from a Word document, without disturbing other highlights the document might contain.

Listing 1: Removing Highlights from a Word Document

Public Sub RemoveHighlight()
   ' Make sure you can access the pane properly.
   Application.ActiveWindow.View = wdNormalView
   
   ' Holds the current pane.
   Dim CurrPane As Pane
   
   ' Access the test document pane.
   Set CurrPane = Application.ActiveWindow.ActivePane
   
   ' Go to the beginning of the document.
   CurrPane.Selection.GoTo wdGoToLine, wdGoToFirst
   
   ' Create a form for getting the color choice.
   Dim GetColor As ColorChoice
   Set GetColor = New ColorChoice
   
   ' Show the form.
   GetColor.Show
   
   ' Determine the return value. If the user cancelled, exit the Sub.
   If Not GetColor.Submitted Then
      MsgBox "Form Cancelled"
      Exit Sub
   End If
   
   ' Creates a search for the word.
   Dim DoSearch As Find
   Set DoSearch = CurrPane.Selection.Find
   
   ' Perform the search.
   With DoSearch
   
      ' Clear any existing formatting information.
      .ClearFormatting
      .Highlight = True
      .MatchCase = False
      .Wrap = wdFindContinue
         
      ' Continue until there is nothing else to search.
      While DoSearch.Execute()
      
         ' Remove the highlight as needed.
         With CurrPane.Selection.FormattedText
            If .HighlightColorIndex = GetColor.SelectedColor Then
               .HighlightColorIndex = wdNoHighlight
            End If
         End With
         
         ' Move to the next character.
         CurrPane.Selection.Move Count:=1
      Wend
   End With
   
   ' Go to the beginning of the document.
   CurrPane.Selection.GoTo wdGoToLine, wdGoToFirst
End Sub

The code must make a few changes to the user settings to ensure the highlights are removed accurately. The first change is to modify the view to the Normal View. These other views, such as Outline View, can present problems when you look for a particular kind of formatting. Next, the code creates the CurrPane object, which points to the current pane. It uses this object to move the cursor to the beginning of the document to make it easier to search. Theoretically, you don't have to make this change, but it's easier when you do.

Now that the environment is prepared, the code displays a dialog box containing the 15 standard highlight colors. The user selects the color of choice and either submits the selection or cancels. If the user clicks Cancel, the macro ends.

It's interesting to note that the code uses a standard Word search to locate the highlight. The next task the code performs is to create a search; notice that the ClearFormatting() method ensures old formatting selections are removed. The DoSearch object can locate a highlight, but it can't search for a particular kind of highlight. Because the search criteria only includes highlighting, every call to DoSearch.Execute()is guaranteed to locate a highlight in the document until the entire document is searched. The search process automatically selects the entire highlight.

To determine whether the current highlight is the right color, the code relies on the HighlightColorIndex property. It compares this value with the GetColor.SelectedColor property (the return value from the dialog box). When the two values match, the code sets the current selection to wdNoHighlight, which clears the highlight.

The search would end immediately after the first highlight matched highlight. The selected text doesn't contain a highlight and the code hasn't told DoSearch to look in the rest of the document. The way around this problem is to move the cursor to the next character in the document and then perform the next DoSearch.Execute() call. When the loop finally fails, all of the highlights of the selected color are removed. The code places the cursor at the beginning of the document.

Accepting, Rejecting, or Leaving Specific Edits

Word's tracking feature is amazing, because it keeps track of everyone who edits the document and precisely what changes they made. Unfortunately, it's difficult to access this information. The only way to work with edits, for the most part, is to check them out one at a time. Unfortunately, you can make errors working with revision marks this way, especially if, for example, you want to track down changes made after a certain time and date. Listing 2 shows one way to track various changes and choose to accept or reject just the changes you want.

Listing 2: Accepting or Rejecting a Single Change Type

Public Sub CheckEdits()
   ' Make sure you can access the pane properly.
   Application.ActiveWindow.View = wdNormalView
   
   ' Holds the current pane.
   Dim CurrPane As Pane
   
   ' Access the test document pane.
   Set CurrPane = Application.ActiveWindow.ActivePane
   
   ' Go to the beginning of the document.
   CurrPane.Selection.GoTo wdGoToLine, wdGoToFirst
   
   ' Create a RevisionChoice dialog box.
   Dim RevTarget As RevisionChoice
   Set RevTarget = New RevisionChoice
   
   ' Get the target revision.
   RevTarget.Show

   ' Determine the return value. If the user cancelled, exit the Sub.
   If Not RevTarget.Submitted Then
      MsgBox "Form Cancelled"
      Exit Sub
   End If
   
   ' Create a Revision object.
   Dim ThisRev As Revision
   
   ' Get the next Revision.
   Set ThisRev = CurrPane.Selection.NextRevision
   
   ' Handle each revision in a loop.
   While Not ThisRev Is Nothing
   
      ' Make sure this is the right kind of edit.
      If ThisRev.Type = RevTarget.ChangeType Then
      
         ' If this is a formatting change. verify it is the correct
         ' type.
         If RevTarget.ChangeType = wdRevisionProperty Then
            If InStr(1, _
                     ThisRev.FormatDescription, _
                     RevTarget.FormatChange, _
                     vbTextCompare) > 0 Then
            
               ' Perform the correct action.
               If RevTarget.AcceptChange Then
                  ThisRev.Accept
               Else
                  ThisRev.Reject
               End If
            End If
         Else
      
            ' Perform the correct action.
            If RevTarget.AcceptChange Then
               ThisRev.Accept
            Else
               ThisRev.Reject
            End If
         End If
      End If
   
      ' Get the next Revision.
      Set ThisRev = CurrPane.Selection.NextRevision
   Wend
End Sub

The code begins by creating CurrPane again. It sets up the pane, as in Listing 1, with the display set to Normal View and the cursor at the beginning of the text. The code displays a dialog box that lets the user choose which edits to accept or reject. In this case, the example concentrates on insertions, deletions, replacements, format changes, and style changes, but you can modify any change and even tie it to a particular author if you wish.

This time the code doesn't rely on a search to find the target edit: it uses a special Revision object. To find a revision with the current document, you must make sure that none of the text is selected. The CurrPane.Selection.NextRevision() method loads ThisRev with the current revision. If there aren't any revisions (or not any more in the current document), then ThisRev will equal Nothing. Consequently, you can perform this check in a loop and locate every revision in the document.

All the information the code needs is in one of the ThisRev properties. The example code shows several, but not all of these properties. The first check you perform depends on the kind of revision mark you want to control. In this example, the focus is on a specific type of edit, so the code focuses on the ChangeType property. Most changes are straightforward, but formatting changes aren't. To determine whether a change is the right type, you must first look for the wdRevisionProperty ChangeType. Unfortunately, this can include any property change, not just character formatting, so the code narrows the search by checking the ThisRev.FormatDescription property. This property is a string that describes the format changes, so you can create an InStr() function setup that locates a particular formatting change such as bold or italic print.

Accepting or rejecting a change is relatively easy once you determine the action the user wants to take. Simply use the Accept() or Reject() method as shown in the code.

You can even use automation to fix errors. For example, someone might use the strikethrough font to delete text, rather than actually delete it. On screen, the changes look similar enough that you could miss one and fixing such an error by hand would be time consuming. Using automation would let you convert the strikethroughs to deleted text in a matter of moments.

Removing Annotation

Word's annotation feature (or comments, depending on the version of Office you use) lets you highlight a specific area of text in the document, and comment on it without changing the document formatting or flow. Reading the comment is as easy as hovering the mouse over it or viewing it in the Reviewing Pane.

However, cleaning up after someone who uses the annotation feature isn't easy. Normally, you have to remove annotation individually. Listing 3 shows a way to remove one reviewer at a time.

Listing 3: Removing Unneeded Annotation

Public Sub RemoveAnnotation()

   ' Get the reviewer's name.
   Dim RevName As String
   RevName = InputBox("Type the name of the reviewer", _
                      "Remove Reviewer Comments")
   ' Create an individual comment.
   Dim ThisComment As Comment
   
   ' Process the comments one at a time.
   For Each ThisComment In Application.ActiveDocument.Comments
   
      ' When the comment author and the requested name match,
      ' delete the comment.
      If ThisComment.Author = RevName Then
         ThisComment.Delete
      End If
   Next
      
End Sub

This code is actually relatively simple compared to the other examples in this article. The comments don't require any type of special search, because Office compiles them into a Comments collection. You can even use a For Each... Next loop to process them.

The code begins by getting the reviewer name using an InputBox(). There isn't a good reason to use anything more complex in this case.

Once the code has the name, it starts processing the comments in a loop. During each pass of the loop, the code checks the reviewer name against the Comment object Author property. When the two match, a simple call to Delete() removes the comment. You can also use an alternative strategy of checking the reviewer initials against the ThisComment.Initial property.

The Bottom Line

Many Office users struggle through hours of mundane and frustrating work cleaning up revision marks in their documents and hoping that nothing gets changed incorrectly in the interim. Even though Office applications, such as Word, don't make the process any easier, they do provide the tools needed to automate the clean up process given a little input.

You could easily script this process based on standard company guidelines and reduce the cleanup process to answering a few questions. With a little more work, you could create a wizard that would take care of all the required inputs and keep the level of required user interaction to a minimum. The result is that cleanup takes seconds, not hours, and is always done perfectly.

Discuss this article in DevSource's new discussion forum!




Discuss Cleaning Up with VBA
 
Very good explanation how to use vba to ascertain text formatting
>>> Post your comment now!
 

 
 
>>> More Techniques Articles          >>> More By John Mueller
 



Microsoft's Future: A Chat With Their CTO, Barry Briggs

Play Video >

All Videos >

Julia explores the Robotics Studio!

Read now >

Messages to Bill Gates!

Read now >

View Now
DevSource RSS FEEDS
XML Want an easy way to keep up with breaking tech news? And the Get DevSource headlines delivered to your desktop with RSS.