Hi.
In case anyone's interested, I've decided to go with a Public Array Variable, with 2 dimensions, of Variant DataType.
If you imagine the second dimension as Rows, then each Row holds information related to 1 of the 7 near identical ComboBox Controls.
If you imagine the first dimension as Columns, then each Column holds information on one of 12 Parameters.
The Parameters include information like the name of the ComboBox control (string), the names of the 3 corresponding Labels (strings), the original and pending values of the ComboBox, the default BackColor and ForeColor of the Controls etc. (More details in Initialize Event)
This way I can use a loop to iterate through each of the 7 ComboBox controls, reading changes in Values and adjusting format of Labels accordingly, or setting variables concerned with saving or discarding changes prior to moving to a new record.
Code as follows
(Sorry I use very long variable names! Try Print View if code window is too restrictive to see full line. PS I compacted "varUserFormControlPropertiesContactsComboBoxes" down to "varUFCPCCboBoxes" for this post!):
In a Standard Module, Declarations section...
Code:
[FONT=Courier New]Public [/FONT][FONT=Courier New]varUFCPCCboBoxes[/FONT][FONT=Courier New](1 To 12, 1 To 7) As Variant[/FONT]
In UserForm Module (UserForm_Initialize Event)...
Code:
[FONT=Courier New]Private Sub UserForm_Initialize()
'<<<...Code Preceeds This...
Dim bytLoop1 As Byte
Dim bytLoop2 As Byte
'[+] [EDIT] Edit Comment
'(i) Assign Values To ?Module / ?Project Level Variables:
'(i) Array Declared As Follows:
' [Public varUFCPCCboBoxes (1 To 12, 1 To 7) As Variant]
' Array Columns Hold The Following Data: Initialised As Follows:
' (1) ComboBox Index Number Store Index Number Top To Bottom (Corresponds To Number In Name Of ComboBox Control)
' (2) ComboBox Name Store Name String
' (3) ComboBox BackColor Store Current Value
' (4) ! Do Nothing (Spare)
' (5) Worksheet Range Corresponding Set Initial Value (Nothing)
' (6) ComboBox Old Value Set Initial Value (0)
' (7) ComboBox Pending Value Set Initial Value (0)
' (8) ComboBox New Value Set Initial Value (0)
' (9) ComboBox Pending Value Differential Set Initial Value (0)
' (10) Label1Front Name Store Name String
' (11) Label2Front Name Store Name String
' (12) LabelRear Name Store Name String
For bytLoop1 = LBound(varUFCPCCboBoxes, 1) _
To UBound(varUFCPCCboBoxes, 1)
For bytLoop2 = LBound(varUFCPCCboBoxes, 2) _
To UBound(varUFCPCCboBoxes, 2)
Select Case bytLoop1
Case 1
Let varUFCPCCboBoxes(bytLoop1, bytLoop2) = bytLoop2
Case 2
Let varUFCPCCboBoxes(bytLoop1, bytLoop2) = "cboContactsCategory" & bytLoop2 & "Counter"
Case 3
Let varUFCPCCboBoxes(bytLoop1, bytLoop2) = _
Me.Controls(varUFCPCCboBoxes(1, bytLoop2)).BackColor
Case 4
'Spare: Do Nothing
Case 5
Set varUFCPCCboBoxes(bytLoop1, bytLoop2) = Nothing
Case 6, 7, 8, 9
Let varUFCPCCboBoxes(bytLoop1, bytLoop2) = 0
Case 10
Let varUFCPCCboBoxes(bytLoop1, bytLoop2) = "lblContactsCategory" & bytLoop2 & "Front1"
Case 11
Let varUFCPCCboBoxes(bytLoop1, bytLoop2) = "lblContactsCategory" & bytLoop2 & "Front2"
Case 12
Let varUFCPCCboBoxes(bytLoop1, bytLoop2) = "lblContactsCategory" & bytLoop2 & "Rear"
End Select
Next bytLoop2
Next bytLoop1
'(i) Reset Loop Variables
Let bytLoop1 = 0
Let bytLoop2 = 0
'...Code Follows This...>>>
End Sub[/FONT]
In UserForm Module (ComboBox_Change and ComboBox_Click Events)...
Code:
[FONT=Courier New]Private Sub cboContactsCategory1Counter_Change()
'(i) Contact Type: "Indirect"
If blnDisableEventsFormInitializePhase = True Then
Exit Sub
End If
'(i) ComboBox New Value: Assign To Array
'[NB] (Pending Column = 3, This ComboBox Row = 1)
'[NB] Val Function: Converts String To Number:
' DataType Of ComboBox Value Is String
' DataType Required For Array Variable Is Number (To Allow "=" Comparison Operations) (Auto Assigned As Double)
Let [/FONT][FONT=Courier New]varUFCPCCboBoxes[/FONT][FONT=Courier New](7, 1) = Val(cboContactsCategory1Counter.Value)
Call gnlControlStatusFormatRefreshContactControls
End Sub
Private Sub cboContactsCategory1Counter_Click()
'(i) Contact Type: "Indirect"
If blnDisableEventsFormInitializePhase = True Then
Exit Sub
End If
'(i) Control ForeColor: Change To Black
' (For Legibility Of DropDown If ForeColor Same As BackColor) (Method Used To Hide Zero Values)
Let cboContactsCategory1Counter.ForeColor = 1 '(black)
Let cboContactsCategory1Counter.Font.Bold = True
End Sub[/FONT]
Also In UserForm Module...
Code:
[FONT=Courier New]Public Sub gnlControlStatusFormatRefreshContactControls()
Dim bytLoop1 As Byte
Let blnChangesPendingContactsUserForm = False
For bytLoop1 = LBound(varUFCPCCboBoxes, 2) _
To UBound(varUFCPCCboBoxes, 2)
If varUFCPCCboBoxes(7, bytLoop1) <> _
varUFCPCCboBoxes(6, bytLoop1) Then
Let varUFCPCCboBoxes(9, bytLoop1) = _
varUFCPCCboBoxes(7, bytLoop1) - _
varUFCPCCboBoxes(6, bytLoop1)
Let blnChangesPendingContactsUserForm = True
Let Me.Controls(varUFCPCCboBoxes(10, bytLoop1)).ForeColor = &H80000008 'blackish (Front1)
Let Me.Controls(varUFCPCCboBoxes(11, bytLoop1)).ForeColor = &H80000008 'blackish (Front2)
Let Me.Controls(varUFCPCCboBoxes(12, bytLoop1)).BackStyle = fmBackStyleOpaque 'cream (Rear)
Else
Let varUFCPCCboBoxes(9, bytLoop1) = 0
Let Me.Controls(varUFCPCCboBoxes(10, bytLoop1)).ForeColor = &HFFFFFF 'white (Front1)
Let Me.Controls(varUFCPCCboBoxes(11, bytLoop1)).ForeColor = &HFFFFFF 'white (Front2)
Let Me.Controls(varUFCPCCboBoxes(12, bytLoop1)).BackStyle = fmBackStyleTransparent 'black (Rear)
End If
With Me.Controls(varUFCPCCboBoxes(2, bytLoop1)) 'combobox
If varUFCPCCboBoxes(7, bytLoop1) = 0 Then
Let .ForeColor = .BackColor 'invisible
Else
Let .ForeColor = 1 'black
End If
End With
Next bytLoop1
If blnChangesPendingContactsUserForm = True Then
Me.cmdContactsLoad.BackColor = &H0& 'black
Me.cmdContactsLoad.ForeColor = &H80C0FF 'tan
Me.cmdContactsLoad.Enabled = False
Me.cmdContactsEdit.BackColor = &H0& 'black
Me.cmdContactsEdit.ForeColor = &H80C0FF 'tan
Me.cmdContactsEdit.Enabled = False
Me.cmdContactsSave.BackColor = &H8000& '?dark green
Me.cmdContactsSave.ForeColor = &HFF00& '?bright green
Me.cmdContactsSave.Enabled = True
Me.cmdContactsCancel.BackColor = &HFF& '?red
Me.cmdContactsCancel.ForeColor = &H80FFFF '?yellow
Me.cmdContactsCancel.Enabled = True
Else
'[+] [EDIT] Change Colours For Load And Save Buttons (Active State)
Me.cmdContactsLoad.BackColor = &H8000& '?dark green
Me.cmdContactsLoad.ForeColor = &HFF00& '?bright green
Me.cmdContactsLoad.Enabled = True
Me.cmdContactsEdit.BackColor = &HFF& '?red
Me.cmdContactsEdit.ForeColor = &H80FFFF '?yellow
Me.cmdContactsEdit.Enabled = True
Me.cmdContactsSave.BackColor = &H0& 'black
Me.cmdContactsSave.ForeColor = &H80C0FF 'tan
Me.cmdContactsSave.Enabled = False
Me.cmdContactsCancel.BackColor = &H0& 'black
Me.cmdContactsCancel.ForeColor = &H80C0FF 'tan
Me.cmdContactsCancel.Enabled = False
End If
End Sub[/FONT]
In Worksheet Module (Worksheet_SelectionChange Event)...
Code:
[FONT=Courier New]'<<<...Code Preceeds This...[/FONT]
[FONT=Courier New] For bytLoop1 = LBound([/FONT][FONT=Courier New]varUFCPCCboBoxes[/FONT][FONT=Courier New], 2) _
To UBound([/FONT][FONT=Courier New]varUFCPCCboBoxes[/FONT][FONT=Courier New], 2)
'(i) Contacts Group In Focus: Load Each Cell Range (Into Individual Variables)
Set [/FONT][FONT=Courier New]varUFCPCCboBoxes[/FONT][FONT=Courier New](5, bytLoop1) = _
rngCurrentContactsGroupInFocusWorksheet.Cells(1, bytLoop1)
'(i) Contacts Group In Focus: Load Each Cell Value (Into Individual Variables) (Initial Value Holder)
Let [/FONT][FONT=Courier New]varUFCPCCboBoxes[/FONT][FONT=Courier New](6, bytLoop1) = _
[/FONT][FONT=Courier New]varUFCPCCboBoxes[/FONT][FONT=Courier New](5, bytLoop1).Value
'(i) Contacts Group In Focus: Load Each Cell Value (Into Individual Variables) (Pending Value Holder)
Let [/FONT][FONT=Courier New]varUFCPCCboBoxes[/FONT][FONT=Courier New](7, bytLoop1) = _
[/FONT][FONT=Courier New]varUFCPCCboBoxes[/FONT][FONT=Courier New](5, bytLoop1).Value
'[+] [EDIT] Add Code for New Values
'(i) Contacts Group In Focus: Load Each Cell Value (Into UserForm ComboBox Controls)
' Reformat Controls To Hide Zero Values
With UserForms(0).Controls([/FONT][FONT=Courier New]varUFCPCCboBoxes[/FONT][FONT=Courier New](2, bytLoop1))
.Value = [/FONT][FONT=Courier New]varUFCPCCboBoxes[/FONT][FONT=Courier New](6, bytLoop1)
If .Value = 0 Then
.ForeColor = .BackColor
Else
.ForeColor = 1
.Font.Bold = True
End If
End With
Next bytLoop1
'...Code Continues...[/FONT]>>>
By the way, regarding 2-dimensional arrays, is it more typical to think of the first dimension as Rows/Records and the second as Columns/Fields or is the reverse more common? Is there a convention, or is it a matter of personal preference?
Thanks for those who offered advice. Shame there's no keyword, but this method will suffice as a workaround, as long as I remember which "Column" holds which parameter! And I don't think that the memory used will be significant (correct me if I'm wrong).
PS. I've recently opted to use the optional word "Let" for clarity. It may be a fad. Cheers...