#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