Search code examples
vbams-access

List FormatConditions of all controls on an Access form


Is it possible to list the conditional formatting of all controls on a form? I'd like to be able to list out all existing conditions so that I can generate code to add/remove the existing conditions. I have inherited some complex forms and want to know what I'm dealing with and then generate some code to toggle the conditional formatting in areas where it is slowing down navigating a continuous form.

This Excel VBA example shows a similar format I'd like to have for Access.
https://stackoverflow.com/a/52204597/1898524


Solution

  • With some inspiration from @June7's example and some code from an article I found by Garry Robinson, I wrote a procedure that answers my question.

    Here's the output in the Immediate window. This is ready to be pasted into a module. The design time property values are shown as a comment.

    txtRowColor.FormatConditions.Delete
    txtRowColor.FormatConditions.Add acExpression, acBetween, "[txtCurrent_Equipment_List_ID]=[txtEquipment_List_ID]"
    With txtRowColor.FormatConditions.Item(txtRowColor.FormatConditions.Count-1)
        .Enabled          = True           ' txtRowColor.Enabled=False
        .ForeColor        = 0              ' txtRowColor.ForeColor=-2147483640
        .BackColor        = 10092543       ' txtRowColor.BackColor=11850710
    End With
    

    You can test this sub from a click event on an open form. I was getting some false positives when checking the Boolean .Enabled property, even when I store the values into Boolean variables first. I don't know why and am researching it, but that is beyond the scope of this question.

    Public Sub ListConditionalFormats(frmForm As Form)
    ' Show all the Textbox and Combobox controls on the passed form object (assuming the form is open).
    ' Output the FormatCondtion properties to the immediate window in a format that is
    ' suitable to be copied into VBA to recreate the conditional formatting.
    ' The design property value is shown as a comment on each condition property row.
        Dim ctl             As Control
        Dim i               As Integer
        Dim bolControlEnabled As Boolean
        Dim bolFormatEnabled As Boolean
    
        On Error GoTo ErrorHandler
    
        For Each ctl In frmForm.Controls
    
            If TypeOf ctl Is TextBox Or TypeOf ctl Is ComboBox Then
                With ctl
                    If .FormatConditions.Count > 0 Then
                        'Debug.Print vbCr & "' " & ctl.Name, "Count = " & .FormatConditions.Count
                        For i = 0 To .FormatConditions.Count - 1
    
                            ' Generate code that can recreate each FormatCondition
                            Debug.Print ctl.Name & ".FormatConditions.Delete"
                            Debug.Print ctl.Name & ".FormatConditions.Add " & DecodeType(.FormatConditions(i).Type) _
                                        & ", " & DecodeOp(.FormatConditions(i).Operator) _
                                        & ", """ & Replace(.FormatConditions(i).Expression1, """", """""") & """" _
                                        & IIf(Len(.FormatConditions(i).Expression2) > 0, ", " & .FormatConditions(i).Expression2, "")
                            Debug.Print "With " & ctl.Name & ".FormatConditions.Item(" & ctl.Name & ".FormatConditions.Count-1)"
    
                            bolControlEnabled = ctl.Enabled
                            bolFormatEnabled = .FormatConditions(i).Enabled
                            'Debug.Print bolControlEnabled <> bolFormatEnabled, bolControlEnabled, bolFormatEnabled
                            If bolControlEnabled <> bolFormatEnabled Then    ' <- This sometimes fails.  BS 2/9/2020
                                'If ctl.Enabled <> .FormatConditions(i).Enabled Then ' <- This sometimes fails.  BS 2/9/2020
                                Debug.Print vbTab & ".Enabled          = " & .FormatConditions(i).Enabled; Tab(40); "' " & ctl.Name & ".Enabled=" & ctl.Enabled
                            End If
    
                            If ctl.ForeColor <> .FormatConditions(i).ForeColor Then
                                Debug.Print vbTab & ".ForeColor        = " & .FormatConditions(i).ForeColor; Tab(40); "' " & ctl.Name & ".ForeColor=" & ctl.ForeColor
                            End If
                            If ctl.BackColor <> .FormatConditions(i).BackColor Then
                                Debug.Print vbTab & ".BackColor        = " & .FormatConditions(i).BackColor; Tab(40); "' " & ctl.Name & ".BackColor=" & ctl.BackColor
                            End If
                            If ctl.FontBold <> .FormatConditions(i).FontBold Then
                                Debug.Print vbTab & ".FontBold         = " & .FormatConditions(i).FontBold; Tab(40); "' " & ctl.Name & ".FontBold=" & ctl.FontBold
                            End If
                            If ctl.FontItalic <> .FormatConditions(i).FontItalic Then
                                Debug.Print vbTab & ".FontItalic       = " & .FormatConditions(i).FontItalic; Tab(40); "' " & ctl.Name & ".FontItalic=" & ctl.FontItalic
                            End If
                            If ctl.FontUnderline <> .FormatConditions(i).FontUnderline Then
                                Debug.Print vbTab & ".FontUnderline    = " & .FormatConditions(i).FontUnderline; Tab(40); "' " & ctl.Name & ".FontUnderline=" & ctl.FontUnderline
                            End If
    
                            If .FormatConditions(i).Type = 3 Then    ' acDataBar
                                Debug.Print vbTab & ".LongestBarLimit  = " & .FormatConditions(i).LongestBarLimit
                                Debug.Print vbTab & ".LongestBarValue  = " & .FormatConditions(i).LongestBarValue
                                Debug.Print vbTab & ".ShortestBarLimit = " & .FormatConditions(i).ShortestBarLimit
                                Debug.Print vbTab & ".ShortestBarValue = " & .FormatConditions(i).ShortestBarValue
                                Debug.Print vbTab & ".ShowBarOnly      = " & .FormatConditions(i).ShowBarOnly
                            End If
                            Debug.Print "End With" & vbCr
                        Next
                    End If
                End With
            End If
        Next
    
        Beep
    
    Exit_Sub:
        Exit Sub
    
    ErrorHandler:
        MsgBox "Error #" & Err.Number & " - " & Err.Description & vbCrLf & "in procedure ListConditionalFormats" _
            & IIf(Erl > 0, vbCrLf & "Line #: " & Erl, "")
        GoTo Exit_Sub
        Resume Next
        Resume
    End Sub
    
    Function DecodeType(TypeProp As Integer) As String
    ' You heed this are there are 4 different ways to setup a CondtionalFormat
    ' https://vb123.com/listing-conditional-formats
    
        Select Case TypeProp
            Case 0
                DecodeType = "acFieldValue"
            Case 1
                DecodeType = "acExpression"
            Case 2
                DecodeType = "acFieldHasFocus"
            Case 3
                DecodeType = "acDataBar"
        End Select
    
    End Function
    
    Function DecodeOp(OpProp As Integer) As String
    ' You need this becuase equations can comprise of = > <> between
    ' https://vb123.com/listing-conditional-formats
    
        Select Case OpProp
            Case 0
                DecodeOp = "acBetween"
            Case 1
                DecodeOp = "acNotBetween"
            Case 2
                DecodeOp = "acEqual"
            Case 3
                DecodeOp = "acNotEqual"
            Case 4
                DecodeOp = "acGreaterThan"
            Case 5
                DecodeOp = "acLessThan"
            Case 6
                DecodeOp = "acGreaterThanOrEqual"
            Case 7
                DecodeOp = "acLessThanOrEqual"
        End Select
    
    End Function