Software

How to use prefix tags and VBA to generate conditional content in Word documents

This simple technique can save you a ton of time by allowing you to use one Word source document to generate several subdocuments. All it takes are a few prefix tags and some VBA code.

dragonimagesistock-527665648.jpg

Image: iStockphoto.com/DragonImages

A lot of readers ask for techniques that display conditional content. Fortunately, there are many ways to do so, and over the next few months we'll review a few of them. In this article, I begin this study with one of the simplest solutions—a bit of VBA code that knows when to hide, and when not to hide, a paragraph, based on a set of identification prefixes in the source document. Technically, you'll learn how to use VBA's Hidden property to hide paragraphs. This technique is valuable when you need several documents that share both common and conditional content. You can generate several specialized documents while maintaining only one source document.

I'm using Word 2016 on a Windows 10 64-bit system, but the code will run in older versions. You can use your own document or download the demonstration .docm or .doc file.

Setup

The first thing you need is a source document with conditional text, similar to the demonstration file shown in Figure A. This document lists scavenger hunt questions for students in kindergarten through sixth grade. Our goal is to use the same (source) document for students in two age groups: kindergarten through second grade and third through sixth grade. The finished product will allow us to specify whether the resulting document displays questions for the younger group or the older group.

Figure A

wordconditionalcontenta.jpg
Our sample document has different questions for two age group levels.

At first glance you might think why bother? The demonstration file is simple on purpose; imagine implementing this technique with a much more complex document and you'll quickly see its value. The goal is to modify and manage one source document instead of several while maintaining the ability to generate several documents from the same source document.

The <> prefix tag at the beginning of each question identifies each group: <1> represents the younger children and <2> represents the older students. You could divide your information into more than two groups; I'm using two to keep the example simple, but you could add a third group for middle school, a fourth for high school, and so on.

Because the VBA depends on the <> symbols to denote the condition, prefix only those paragraphs you want evaluated conditionally. In addition, the code evaluates paragraphs as denoted by the paragraph mark or hard return. In other words, the code looks for the content between the tag and the first hard return it encounters. Using the identification value inside the tag, the code decides whether to hide the content or not.

Once you have your source document, you're ready to add the code that allows a user to specify which questions to display. Before adding that code, you'll want to do two things if you're using the Ribbon version of Word: Save the document as a macro-enabled file and display the Developer tab.

Save the document

If you're using a menu version of Word, you can skip this section and the next. Ribbon-version users must save the document as a macro-enabled file as follows:

  1. Click the File tab.
  2. In the left pane, choose Save As.
  3. Enter a name for the file.
  4. Choose Word Macro-Enabled Document (*.docm), as shown in Figure B.
  5. Click Save.

Figure B

wordconditionalcontentb.jpg
Save your source document as a macro-enabled file.

Display the Developer tab

You'll use options on the Developer tab to enter and run the code. If this tab isn't visible, display it as follows:

  1. From the Quick Access Toolbar dropdown, select More Commands. Or click the File tab, choose Options, and then choose Customize Ribbon.
  2. In the Main Tabs list (to the right), check the Developer option, as shown in Figure C.
  3. Click OK to return to your document.

Figure C

wordconditionalcontentc.jpg
Add the Developer tab to the Ribbon.

Add the code

Now you're ready to add the code that determines which questions to hide. To enter the code in Listing A, click the Developer tab and then click Visual Basic in the Code group to open the Visual Basic Editor (VBE).

Listing A

Sub ProcessHide()
'Hide questions according to age group.
'<1> represents questions for k through 2nd grade.
'<2> represents questions for 3rd through sixth grade.
    
    Dim ToShow As Integer
    Dim myPara As Paragraph
    Dim myRange As Range
    Dim doc As Document
    
    Set myRange = Range
    Set doc = ActiveDocument
     
'Enable error-handling rutine.
    On Error GoTo ErrorHandler
'Show all previously hidden text before beginning.
'There shouldn't be any; added as a precaution in case someone saves the original while questions are hidden.
    doc.Range.Font.Hidden = False
    
'Ask user for age group to display; the input value must be 1 or 2.
'You can use an If instead: If ToShow > 2 or ToShow < 1 Then...
'-----Add more categories here.
    
ToShow = InputBox("Please enter 1 or 2 to indicate age group.")
    Select Case ToShow
        Case Is = 1 'Do Nothing
        Case Is = 2 'Do Nothing
        Case Is > 2
            MsgBox "Please enter the value 1 or 2.", vbOKOnly, "Error"
        Case Is < 1
            MsgBox "Please enter the value 1 or 2.", vbOKOnly, "Error"
        Case Else   'Catch everything else
            'Appropriate response code.
    End Select
       
'Determine if current question matches show or hide group.
'First check for tag character < and ignore any paragraphs that don't begin with this character.
'If input value and tag value match, hide first tag.
    For Each myPara In doc.Paragraphs
        If InStr(1, myPara, "<") Then
            If ToShow = myPara.Range.Characters(2) Then
                myRange.SetRange start:=myPara.Range.start, End:=myPara.Range.start + 3
                myRange.Font.Hidden = True
            End If
        End If
    Next
    
'If input value and tag value don't match, hide myPara.
    For Each myPara In doc.Paragraphs
        If InStr(1, myPara, "<") Then
            If ToShow <> myPara.Range.Characters(2) Then myPara.Range.Font.Hidden = True
        End If
    Next
    
Exit Sub
                      
ErrorHandler:
    Select Case Err.Number
        Case Is = 13
            MsgBox "Please enter the value 1 or 2.", vbOKOnly, "Error"
            Exit Sub
        Case Else
            MsgBox Err.Description
            doc.Range.Font.Hidden = False
            Exit Sub
    End Select

End Sub


In the Projects Explorer, choose This Document and enter the code shown in Figure D. If you have more than one Word document open, be careful to select the right file.

NOTE: Don't try to copy the VBA code from this web page because the VBE will complain about special web characters. Instead, use the downloadable demonstration files.

Figure D

wordconditionalcontentd.jpg
Enter the code.

Make sure error-handling is set correctly by choosing Options from the Tools menu. Next, click the General tab, select Break On Unhandled Errors in the Error Trapping section, and click OK.

Save your work and return to your Word document to run the macro. Click the Developer tab and then click Macros in the Code group. In the resulting dialog, choose ProcessHide, as shown in Figure E, and click Run.

Figure E

wordconditionalcontente.jpg
Run the macro.

When the macro displays the input box, enter the value 1 as shown in Figure F. Doing so will hide the questions prefixed with the <2> tag and hide the <1> tags for the remaining questions, as shown in Figure G. If you enter 2, the macro will hide questions prefixed with <1> and hide the <2> tags. In other words, enter the value that represents the age group you want to display. Admittedly, this part of the routine could be more user friendly. Your users will have to know what the values 1 and 2 represent. I opted for simplicity so we could focus on the technique and not specialization.

Figure F

wordconditionalcontentf.jpg
Enter the value 1 or 2 in the input box.

Figure G

wordconditionalcontentg.jpg
The macro hid the questions for age group 2.

Also notice that the macro didn't hide the sentence without a <> prefix. The code ignores any paragraph that doesn't begin with the < character. Now, let's take a closer look at the code so you can customize it for your documents.

The first few lines declare and define a few variables, enable error-handling, and unhide any questions that might have been previously hidden. This could happen if a user saves the document after running the macro. Train your users not to do that—instead, run the macro, print out the number of scavenger hunts required, and exit without saving. Or run the macro and rename the document, so as not to overwrite the source document.

The InputBox() function prompts the user for a value, and the Select Case forces the input value to be a 1 or a 2. If you add more conditions (more age groups), be sure to update the Select Case accordingly. The first two Case Is statements aren't required, but I added them to be comprehensive; you might want to do something a bit different when applying this technique to your own documents.

The For Each block cycles through each paragraph in the document. In this case, each question is a paragraph because each question is followed with a paragraph mark (hard return). If the first character in the current paragraph (myPara) is the < character, the If block compares the user's input value (ToShow) to the second character in the paragraph—the values 1 and 2 in the prefix tags. If those two values are the same, the code hides the prefix tag but not the question.

The next For Each block works similarly but looks for a mismatch between the ToShow variable and the prefix value. When they don't match, the code hides the entire paragraph—the prefix and the question.

By using conditional text, you need update only one document when you need to make changes to the source questions. For instance, you might have questions in both age groups that refer to the bullfrog exhibit. If you do away with the exhibit, you can open the source document and delete all related questions in only the source document.

If you have several different documents for different categories, you can see the value—updating one source or master document is more efficient than updating several subdocuments. You'll most likely use this in documents that contain both common and conditional text.

More customization

This example is simple on purpose so we can focus on the code and how it works. You can add more conditions (age groups) by adding tag prefixes such as <3>, <4>, and so on. Simply adapt the first Select Case to accept the new values. You don't need to change anything else. You could even add an answer to each question and hide them from students but display them for educators, but this article doesn't include that solution. You might consider running the macro as an AutoExec macro. Doing so complicates maintenance, but it will be much simpler for your users.

Send me your question about Office

I answer readers' questions when I can, but there's no guarantee. Don't send files unless requested; initial requests for help that arrive with attached files will be deleted unread. You can send screenshots of your data to help clarify your question. When contacting me, be as specific as possible. For example, "Please troubleshoot my workbook and fix what's wrong" probably won't get a response, but "Can you tell me why this formula isn't returning the expected results?" might. Please mention the app and version that you're using. I'm not reimbursed by TechRepublic for my time or expertise when helping readers, nor do I ask for a fee from readers I help. You can contact me at susansalesharkins@gmail.com.

Also read...

About Susan Harkins

Susan Sales Harkins is an IT consultant, specializing in desktop solutions. Previously, she was editor in chief for The Cobb Group, the world's largest publisher of technical journals.

Editor's Picks

Free Newsletters, In your Inbox