Form Field Specific Menu Items in MS Word
Posted by Derek Mang on April 3rd, 2007
Microsoft Word provides a lot of what's needed, but sometimes you need more! I have developed a few Word-based forms, and would like to share a technique I use in customizing a dropdown menu.
A lot of forms are set up with information within MS Word tables. Typically MS Word forms are protected allowing the user to complete form fields only. In a recent example, there was the need for several date fields as well as a user email address field. I wanted to provide as much as possible to reduce user keystrokes, and maintain consistency.
To do this, I wanted to offer specific, custom menu choices for specific information.
There are a couple aspects which make this pretty simple.
1. Adding new styles to the document. This is done at document open time, by calling the AddNewStyles sub. In addition to adding the new styles, specific formfields have their styles set to the new styles.
   Call UnprotectDoc
   Call RemoveStyles
   ActiveDocument.Styles.Add Name:="smartDocEmail"
   ActiveDocument.Styles.Add Name:="smartDocCalendar"
   ActiveDocument.FormFields("txtDateIssued").Range.Style = "smartDocCalendar"
   ActiveDocument.FormFields("txtClientEmail").Range.Style = "smartDocEmail"
   ActiveDocument.FormFields("txtTargetDate").Range.Style = "smartDocCalendar"
   Call ProtectDoc
End Sub
Sub RemoveStyles()
   On Error Resume Next
   ActiveDocument.Styles("smartDocEmail").Delete
   ActiveDocument.Styles("smartDocCalendar").Delete
End Sub
2. The Protectdoc and Unprotectdoc subs are called as needed, and are here for reference. This example protects sections 1 and 3 of the document. The NoReset:=True is important. Without it, the document form fields are reinitialized whenever the protect method is executed.
   ActiveDocument.Sections(1).ProtectedForForms = True
   ActiveDocument.Sections(2).ProtectedForForms = False
   ActiveDocument.Sections(3).ProtectedForForms = True
   ActiveDocument.Protect Password:="smartDoc", NoReset:=True,Type:=wdAllowOnlyFormFields
End Sub
Sub UnprotectDoc()
   If ActiveDocument.ProtectionType wdNoProtection Then
       ActiveDocument.Unprotect Password:="smartDoc"
   End If
End Sub
3. Update the "Form Fields" dropdown menu. When a form field is right-clicked, the "Form Fields" menu is shown. The code below removes a "popup" menu item "smartDoc" and adds it back with 2 choices. A keypoint here is that the Popup item itself has "Onaction" specified. This is where we're going to decide on what menu item should be available.
   Dim cb As CommandBar
   Dim cbp As CommandBarPopup
   Dim cbc As CommandBarControl
   Dim c As Integer
   Set cb = Application.CommandBars(strName)
   For c = cb.Controls.Count To 1 Step -1
       If UCase(cb.Controls(c).Tag) = "SMARTDOC" Then
           cb.Controls(c).Delete
       End If
   Next c
   Set cbp = cb.Controls.Add(msoControlPopup)
   With cbp
       .BeginGroup = True
       .Caption = "smartDoc"
       .Tag = "smartDoc"
        .OnAction = "SetSmartdocMenu"
End With
   Set cbc = cbp.Controls.Add(msoControlButton)
   With cbc
       .Caption = "Calendar"
       .OnAction = "ShowCalendar"
       .Style = msoButtonIconAndCaption
       .BeginGroup = True
       .FaceId = 125
       .Tag = "smartDoc"
       .Visible = True
       .Enabled = False
   End With
   Set cbc = cbp.Controls.Add(msoControlButton)
   With cbc
       .Caption = "eMail Address..."
       .OnAction = "GetAddress"
       .Style = msoButtonIconAndCaption
       .BeginGroup = True
       .FaceId = 45
       .Tag = "smartDoc"
       .Visible = True
       .Enabled = False
   End With
   Set cbc = Nothing
   Set cbp = Nothing
   Set cb = Nothing
End Sub
4. The sub below gets invoked prior to displaying its dropdown items.
1. Establish the popup object on the dropdown menu.
2. Disable both items
3. Unprotect the doc to make the field style available.
4. Reset the enabled property of the dropdown items depending on the field style.
5. Protect the document
   Dim cb As CommandBar
   Dim cbp As CommandBarPopup
   Set cb = Application.CommandBars.ActionControl.Parent
   Set cbp = cb.Controls(cb.Controls.Count)
   cbp.Controls(1).Enabled = False
   cbp.Controls(2).Enabled = False
   If Selection.Information(wdWithInTable) = True Then
       Call UnprotectDoc
       Select Case Selection.Style
            Case "smartDocCalendar"
                 cbp.Controls(1).Enabled = True
                 cbp.Controls(2).Enabled = False
            Case "smartDocEmail"
                 cbp.Controls(1).Enabled = False
                 cbp.Controls(2).Enabled = True
            Case Else
       End Select
       Call ProtectDoc
   End If
   Set cbp = Nothing
   Set cb = Nothing
End Sub
This may not be the most elegant solution, but it serves the purpose.


