Hi David,
As with most things in Word, the choices are complicated. Generally, I would recommend using content controls for all the entry "fields" (note, these are not fields in Word's technical jargon).
There are a few reasons you may not want to use content controls: If the users of the form will have Word for Windows version 2007 or earlier (which don't support check box content controls) or Word for Mac earlier than Office 2016 version 15.23 (see https://answers.microsoft.com/en-us/office/forum/office_2016-word/content-controls-in-word-2016-for-mac).
In those cases, you can use legacy form fields.
I don't recommend ActiveX controls for large forms like this. They're very old technology and not very secure, and they're sometimes ill-behaved. (Ref:
https://docs.microsoft.com/en-us/previous-versions/office/developer/office-xp/aa140269(v=office.10)#appropriateness-for-the-task)
With either content controls or legacy form fields, the VBA code for filling in the form must be different from the ones I showed for using bookmarks. The main difference is that both kinds of those objects have their own "names" that are accessed differently
than a bookmark's name.
For Content Controls:
For each content control, select it and click the Properties button on the ribbon. In the dialog, enter its "name" in either or both the Title and Tag boxes. Word does not require that each control have a unique name, but the VBA code will be simpler if
you do assign unique names. Note also that code referring to these names is case-sensitive, so be consistent in typing the names.
To "protect" the form, select the text that should be non-editable and all its adjacent content controls, click the Group button on the Developer ribbon, and click Group in the dropdown. To leave free-entry areas such as your Documents Checked, make multiple
groups and leave these areas outside any group. (Alternatively, you can put a Rich Text content control in each of those areas and then group the entire form.) Any text that is in a group but not inside a content control will not be editable.
In the code, getting access to a particular content control is complicated by the fact that the Title and Tag need not be unique. The functions ActiveDocument.SelectContentControlsByTitle and ActiveDocument.SelectContentControlsByTag return an array of content
controls instead of a single one. If the titles and tags are unique, the array will have only one entry. If your form contains check boxes with titles CH1 and CH2, then the code
Dim cc As ContentControl
Set cc = ActiveDocument.SelectContentControlsByTitle("CH1")(1)
will return the CH1 control.
Regarding where this code goes: In the macro editor's Project pane, expand your template's project and the Microsoft Word Objects folder under that. Double-click the ThisDocument object. In the code pane on the right, open the dropdown that says "General"
and choose "Document". Open the other dropdown and choose ContentControlOnExit. That will insert this pair of lines in the code window:
Private Sub Document_ContentControlOnExit(ByVal ContentControl As ContentControl, Cancel As Boolean)
End Sub
Your code to update the content controls and hide/unhide the table rows goes inside this procedure. The variable named ContentControl passed in as the subroutine's argument will refer to the control that has just been exited, and you can use it to determine
what action to take. (Hint: rename that variable to CC to avoid confusion between the variable name and the data type.) Start with an If or Select Case to test whether the control is one that you need to handle; if not, immediately do an Exit Sub.
To make the check boxes exclusive, use code like this:
Private Sub Document_ContentControlOnExit( _
ByVal CC As ContentControl, Cancel As Boolean)
Dim ccCH1 As ContentControl
Dim ccCH2 As ContentControl
Dim ccATnum As ContentControl
Set ccCH1 = ActiveDocument.SelectContentControlsByTag("CH1")(1)
Set ccCH2 = ActiveDocument.SelectContentControlsByTag("CH2")(1)
Set ccATnum = ActiveDocument.SelectContentControlsByTag("ATnumber")(1)
Select Case CC.Tag ' tag of control being exited
Case "CH1"
If CC.Checked Then
ccCH2.Checked = False
ccATnum.Range.Text = "AT1"
Else
ccCH2.Checked = True
ccATnum.Range.Text = "AT2"
End If
Case "CH2"
If CC.Checked Then
ccCH1.Checked = False
ccATnum.Range.Text = "AT2"
Else
ccCH1.Checked = True
ccATnum.Range.Text = "AT1"
End If
'Case "some other control's tag"
' other code
Case Else
Exit Sub
End Select
End Sub
In order to be able to hide rows in the table, those rows will have to be excluded from any grouping.
For Legacy Form Fields:
In the Properties dialog of each legacy form field, you should replace the default value in the Bookmark box with the field's name.
It's a little backwards, but next you need to write the macro that will handle the value of the check box -- at least type in the Sub statement, even if you're leaving the content of the subroutine empty at this point. Once that's defined, the macro's name
will become available in the Exit dropdown in the field's Properties dialog. Select it and click OK. Although you can write a separate macro for each check box, it's more efficient to write one macro that handles both, like the code above.
To make the check boxes exclusive, use code like this:
Sub ExitCH()
Dim ffCH1 As FormField
Dim ffCH2 As FormField
Dim ffATnum As FormField
Set ffCH1 = ActiveDocument.FormFields("CH1")
Set ffCH2 = ActiveDocument.FormFields("CH2")
Set ffATnum = ActiveDocument.FormFields("ATnumber")
If Selection.FormFields.Count = 1 Then
Select Case Selection.FormFields(1).Name
Case "CH1"
If ffCH1.CheckBox.Value = True Then
ffCH2.CheckBox.Value = False
ffATnum.Result = "AT1"
Else
ffCH2.CheckBox.Value = True
ffATnum.Result = "AT2"
End If
Case "CH2"
If ffCH2.CheckBox.Value = True Then
ffCH1.CheckBox.Value = False
ffATnum.Result = "AT2"
Else
ffCH1.CheckBox.Value = True
ffATnum.Result = "AT1"
End If
Case Else
Exit Sub
End Select
End If
End Sub
To be able to hide the four rows, add a bookmark that encloses them, and change the bookmark's .Range.Font.Hidden value to True or False as appropriate. This will work even though the form document is protected for filling in forms.