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.
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.
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.
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:
- Click the File tab.
- In the left pane, choose Save As.
- Enter a name for the file.
- Choose Word Macro-Enabled Document (*.docm), as shown in Figure B.
- Click Save.
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:
- From the Quick Access Toolbar dropdown, select More Commands. Or click the File tab, choose Options, and then choose Customize Ribbon.
- In the Main Tabs list (to the right), check the Developer option, as shown in Figure C.
- Click OK to return to your document.
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).
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.
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.
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.
Enter the value 1 or 2 in the input box.
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.
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 firstname.lastname@example.org.