Вложенные операторы IF для пользовательской формы

#vba #excel #userform

#vba #excel #пользовательская форма

Вопрос:

Моя пользовательская форма предоставляет пользователю выбор из 3 цветов [красный, зеленый, синий] для «высоких значений» и «Низких значений». Однако пользователь должен выбрать один цвет для каждого, а не один и тот же цвет для высоких и низких значений, конечно. Цвета выделяют низкие и высокие значения в данных, чтобы различать их. Я прикрепил изображение моей пользовательской формы и ту часть моего кода, где я не могу назначить различным параметрам разные цвета, чтобы это работало. Буду признателен за любую помощь в исправлении моей логики IF.

        Public Function ShowInputsDialog(LowColor As Long, HighValue As Single, HighColor As Long, LowValue As Single)
Call Initialize
Me.Show
If Not Cancel Then
    If optRed1.Value Then '<-- Assigning the 3 colors to the Low Values
    LowColor = vbRed
    ElseIf optGreen1.Value Then
    LowColor = vbGreen
    Else
    LowColor = vbBlue
    End If
    If optRed2.Value Then HighColor = vbRed  '<-- Assigning the 3 colors to the High Values
    ElseIf optGreen2.Value Then HighColor = vbGreen
    Else
    HighColor = vbBlue
    End If
 End If
    HighValue = txtHigher.Value
    LowValue = txtLower.Value
ShowInputsDialog = Not Cancel
Unload Me
End Function
  

Пользовательская форма

Ответ №1:

Я бы поступил следующим образом:

  • добавьте BeforeUpdate() событие для каждого переключателя

  • пусть этот обработчик событий позволяет элементу управления принимать значение, введенное пользователем, если оно совместимо со своим «аналогом» элемента управления

    это с помощью модуля, который проверяет активное управляющее значение на соответствие его «аналогу»

например, вы могли бы добавить в панель кода вашей пользовательской формы следующий код:

 Private Sub optBlue1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
    CrossCheck
End Sub

Private Sub optBlue2_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
    CrossCheck
End Sub

Private Sub OptGreen1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
    CrossCheck
End Sub

Private Sub OptGreen2_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
    CrossCheck
End Sub

Private Sub OptRed1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
    CrossCheck
End Sub

Private Sub OptRed2_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
    CrossCheck
End Sub

Private Sub CrossCheck()
    Dim optNr As String, optName As String

    With Me
        If .ActiveControl.ActiveControl.Value Then
            optName = .ActiveControl.ActiveControl.name
            optNr = Mid(optName, Len(optName), 1)
            .ActiveControl.ActiveControl.Value = Not (.ActiveControl.ActiveControl.Value = .Controls(Replace(optName, optNr, IIf(optNr = "1", "2", "1"))).Value)
        End If
    End With
End Sub
  

конечно, Class подход мог бы облегчить задачу написания всех этих Private Sub optXXXX_BeforeUpdate() обработчиков событий и предоставить вам больше гибкости как для текущего кодирования, так и для будущих улучшений кода, но если вы придерживаетесь только трех переключателей, это может быть немного излишним

Кстати, все вышесказанное означает, что ваш ShowInputsDialog() sub не должен заботиться о совместимости с кнопками опций и может выполнять свою обычную работу по назначению значения, для которой я бы использовал синтаксис Select Case вместо If Then - Else If Then - End If одного:

 If Not Cancel Then
    Select Case True
        Case OptRed1.Value
            LowColor = vbRed
        Case OptGreen1.Value
            LowColor = vbGreen
        Case Else
            LowColor = vbBlue
    End Select

    Select Case True
        Case OptRed2.Value
            HighColor = vbRed
        Case OptGreen2.Value
            HighColor = vbGreen
        Case Else
            HighColor = vbBlue
    End Select
End If
  

или вы могли бы использовать вспомогательную функцию:

 Function GetColor(opt1 As MSForms.OptionButton, opt2 As MSForms.OptionButton) As Long
    Select Case True
        Case opt1.Value
            GetColor = vbRed
        Case opt2.Value
            GetColor = vbGreen
        Case Else
            GetColor = vbBlue
    End Select
End Function
  

и просто напишите

 If Not Cancel Then        
    LowColor = GetColor(OptRed1, OptGreen1)
    HighColor = GetColor(OptRed2, OptGreen2)        
End If