Мне кажется, я понимаю, что вы пытаетесь сделать, и надеюсь, что эти замечания помогут вашему коду.Итак, несколько комментариев ...
- Всегда используйте
Option Explicit
.Независимо от того, какой пример кода вы найдете в Интернете, использование этой привычки в будущем вам очень поможет. - Это БОЛЬШАЯ помощь в использовании промежуточных переменных в вашем коде, которая делает код самодокументируемым.При назначении промежуточных значений и объектов штраф не взимается, поэтому используйте это в своих интересах.
- Разделите логические блоки на отдельные подпрограммы или функции.Это делает ваш код «функционально изолированным» - это означает, что каждый блок кода имеет определенный фокус, и если вам нужно изменить его, вы изменяете его только в одном месте.Это также облегчает чтение вашего кода без прокрутки вверх и вниз, чтобы получить представление о общей логике.
В случае вашего Worksheet_Change
кода события я могу уменьшить логику долегче понять поток:
Option Explicit
Private Sub Worksheet_Change(ByVal target As Range)
Dim groupsRange As Range
Dim currencyRange As Range
Dim valuesRange As Range
Set groupsRange = ActiveSheet.Range("C10:AA10")
Set currencyRange = ActiveSheet.Range("C66:AA66")
Set valuesRange = ActiveSheet.Range("C11:AA11")
If Not Intersect(groupsRange, target) Is Nothing Then
ShowActiveGroups target
ElseIf Not Intersect(currencyRange, target) Is Nothing Then
ShowCurrency target
ElseIf Not Intersect(valuesRange, target) Is Nothing Then
ShowValues target
End If
If target.Count > 1 Then Exit Sub
If (target.Row = 15) Or (target.Row = 18) Or (target.Row = 21) Then
CheckMultiSelect target
End If
End Sub
Ясно, что я, возможно, не получаю «точку» ваших диапазонов (используя «группы», «валюта», «значения»), но вы должны использовать описательныйимена, которые облегчают понимание ЧТО и ПОЧЕМУ логика работает в определенных разделах.
Код для Subs
, вызываемый в событии Worksheet_Change
, помещается в отдельный модуль и всеони помечены как Public
.У каждого из них сходная логика, и здесь есть несколько вещей, которые работают.
В каждом из логических блоков (т. Е. В коде
Sub
в данном случае) вы должны выполнить шаги, чтобы точно установить
, на какой лист ссылается.Очень важно всегда
полностью квалифицировать ссылки на диапазон (см. # 5) .Самый простой способ сделать это (без очень длинных составных операторов) - использовать промежуточные переменные.
Таким образом, в каждой из вышеперечисленных подпрограмм «Show» я устанавливаю ссылку на Worksheet
целевой ячейки (ячейки, которая вызвала событие Worksheet_Change
).
Dim targetWS As Worksheet
Set targetWS = target.Parent
Попробуйте определить константы для, казалось бы, «случайных» чисел или значений, которые не имеют реального значения вне контекста вашей рабочей таблицы.
В вашем случае вы ссылаетесь на множество разных строк и скрываете / скрываете их.Понятия не имею почему.Но если бы вы могли «назвать» строки в вашем коде, это могло бы иметь больше смысла.Вот несколько примеров, которые я использовал:
Const RED_GROUP_1 As String = "14:58"
Const RED_GROUP_2 As String = "10"
Const GREEN_GROUP_1 As String = "17:58"
Const GREEN_GROUP_2 As String = "14:16"
Итак, первые три подпрограммы «Показать» могут выглядеть примерно так:
Public Sub ShowActiveGroups(ByRef target As Range)
Dim targetWS As Worksheet
Set targetWS = target.Parent
Const RED_GROUP_1 As String = "14:58"
Const RED_GROUP_2 As String = "10"
Const GREEN_GROUP_1 As String = "17:58"
Const GREEN_GROUP_2 As String = "14:16"
With targetWS
Select Case target.Value
Case "Select One"
.Rows(RED_GROUP_1).EntireRow.Hidden = True
.Rows(RED_GROUP_2).EntireRow.Hidden = False
Case 1
.Rows(GREEN_GROUP_1).EntireRow.Hidden = True
.Rows(GREEN_GROUP_2).EntireRow.Hidden = False
Case 2
.Rows("20:58").EntireRow.Hidden = True
.Rows("14:19").EntireRow.Hidden = False
' ...
Case Else
'--- what should we do if it's not a valid value?
End Select
End With
End Sub
Public Sub ShowCurrency(ByRef target As Range)
Dim targetWS As Worksheet
Set targetWS = target.Parent
Const CURRENCY_LINE As String = "67"
With targetWS
Select Case target.Value
Case "GBP", "USD", "Yuan", "EUR", "LRD", "Select One"
.Rows(CURRENCY_LINE).EntireRow.Hidden = True
Case "Other"
.Rows(CURRENCY_LINE).EntireRow.Hidden = False
Case Else
'--- what should we do if it's not a valid value?
End Select
End With
End Sub
Public Sub ShowValues(ByRef target As Range)
Dim targetWS As Worksheet
Set targetWS = target.Parent
Const MONEY_LINE As String = "13"
Const PERCENT_LINE As String = "12"
With targetWS
Select Case target.Value
Case "$"
.Rows(MONEY_LINE).EntireRow.Hidden = True
.Rows(PERCENT_LINE).EntireRow.Hidden = False
Case "%"
.Rows(MONEY_LINE).EntireRow.Hidden = False
.Rows(PERCENT_LINE).EntireRow.Hidden = True
Case "Select One"
.Rows(MONEY_LINE).EntireRow.Hidden = True
.Rows(PERCENT_LINE).EntireRow.Hidden = True
Case Else
'--- what should we do if it's not a valid value?
End Select
End With
End Sub
Наконец, у меня всегда были проблемы с проверкой данных/ multi-select код, который вы нашли в webz .Так что я вбрасываю тот, который я использую, у которого есть пара легких модов.Этот код также входит в модуль обычного кода.
Public Sub CheckMultiSelect(ByRef target As Range)
Dim targetWS As Worksheet
Set targetWS = target.Parent
On Error Resume Next
Dim dvCheck As Range
Set dvCheck = targetWS.Cells.SpecialCells(xlCellTypeAllValidation)
If dvCheck Is Nothing Then Exit Sub
Application.EnableEvents = False
'--- only allow multi-select if the cell has defined data validation
If Not Intersect(dvCheck, target) Is Nothing Then
Dim currentValue As String
Dim oldValue As String
currentValue = target.Value
Application.Undo
oldValue = target.Value
If oldValue = vbNullString Then
target.Value = currentValue
Else
If InStr(1, oldValue, currentValue) = 0 Then
target.Value = oldValue & "," & currentValue
Else
If currentValue = vbNullString Then
target.Value = vbNullString
Else
target.Value = oldValue
End If
End If
End If
End If
Application.EnableEvents = True
End Sub
Используя приведенный выше код как в модуле рабочего листа, так и в модуле обычного кода, я успешно смог выполнить некоторые операции в вашем исходном вопросе.