Search code examples
vbams-wordword-contentcontrol

Change state of content control checkbox based on other checkboxes state


I have a template .dotm in which I have multiple checkbox content controls. They are organised in groups as follows:

[chk_1] Attach all the items listed below:

      [chk_1_1] Item A
      [chk_1_2] Item B
      [chk_1_3] Item C

[chk_2] Send the details provided below:

      [chk_2_1] Info A
      [chk_2_2] Info B
      [chk_2_3] Info C

What I'm trying to do is a method to autocheck chk_1 if any of the subitems are checked, as some sort of failproof system, if the user forget to manually check chk_1. So far, I've managed to do this manually, as follows:

Private Sub btnSubmit_Click()
Dim ctl As ContentControl
For Each ctl In ActiveDocument.ContentControls
If ctl.Type = wdContentControlCheckBox Then
    If ctl.Tag = "chk_1_1" or ctl.Tag = "chk_1_2" or ctl.Tag = "chk_1_3" Then
        If ctl.Checked = True Then
            ActiveDocument.SelectContentControlsByTag("chk_1").Item(1).Checked = True
        End If
    End If
End If         
Next
Dim ctl2 As ContentControl
For Each ctl2 In ActiveDocument.ContentControls
If ctl2.Type = wdContentControlCheckBox Then
    If ctl2.Tag = "chk_2_1" or ctl2.Tag = "chk_2_2" or ctl2.Tag = "chk_2_3" Then
        If ctl2.Checked = True Then
            ActiveDocument.SelectContentControlsByTag("chk_2").Item(1).Checked = True
        End If
    End If
End If         
Next
End Sub

This code is executed when an ActiveX button btnSubmit is clicked and autotick the parent checkboxes, if any of the child checkboxes are ticked.

I want to simplify the code because, over the time, there will be multiple groups with 20+ checkboxes each and the code will be harder to write.

Is there a way to use a string or that checks for the state of all the checkboxes that are tagged chk_x_y and then to modify the state chk_x?


Solution

  • Something like this could be easier to read and maintain.

    If the control naming is consistent there should be no need to check whether the control is a checkbox - the name will identify that.

    Select Case is an alternative to If when using multiple "or" criteria - somewhat easier to read... And in this case it can compare the common section of the tag names for a group. "Greater than" will pick up the longer tag names under the upper-level control that has only the common characters.

    Note that you need work backwards through the alphabet when using this approach.

    Then, the actual actions performed each time are put in a separate procedure, called by each "Case".

    So, when writing the code for multiple controls you can pretty much copy/paste the Case then alter the two tag strings for each control set.

    Sub GetCC_Set()
        Dim cc As Word.ContentControl
        Dim doc As Word.Document
    
        Set doc = ActiveDocument
        For Each cc In doc.Contentcontrols
            Select Case cc.tag
                Case Is > "ck2"
                    Debug.Print 2
                    CheckItems "ck2", cc
                Case Is > "ck1"
                    Debug.Print 1
                    CheckItems "ck1", cc
                Case Else
                    Debug.Print cc.tag
            End Select
        Next                
    End Sub
    
    Sub CheckItems(tag As String, cc As Word.ContentControl)
        If cc.Checked = True Then
            cc.Parent.SelectContentControlsByTag(tag).Item(1).Checked = True
        End If
    End Sub