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
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