По большому счету код ниже делает то, что вы описываете. Пожалуйста, установите его на листе кода на листе, на котором вы хотите действие (НЕ стандартный модуль кода). Правильное расположение имеет решающее значение для его функционирования.
Private Sub Worksheet_Activate()
Cells(5, "S").Select
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Rng As Range
Dim C As Long
Dim R As Long
If Target.Cells.CountLarge > 1 Then Exit Sub
Set Rng = Application.Union(Range("S5"), Range("C6"))
For C = 5 To 19 Step 2
Set Rng = Application.Union(Rng, Range(Cells(11, C), Cells(34, C)))
Next C
If Not Application.Intersect(Target, Rng) Is Nothing Then
Select Case Target.Row
Case 5
Rng.Areas(2).Select
Case 6
With Rng.Areas(1)
If Len(.Value) = 0 Then
GoBack .Row, .Column
Else
Rng.Areas(3).Cells(1).Select
End If
End With
Case Else
C = Rng.Areas.Count
With Rng.Areas(C)
If Target.Address = .Cells(.Cells.Count).Address Then
Cells(36, "H").Select
Else
With Target
R = .Row
C = .Column + 2
End With
If C > .Column Then
R = R + 1
C = Rng.Areas(3).Column
End If
Cells(R, C).Select
End If
End With
End Select
End If
End Sub
Private Sub GoBack(R As Long, _
C As Long)
Dim Cell As Range
Set Cell = Cells(R, C)
MsgBox "Cell " & Cell.Address(0, 0) & " must be filled first.", _
vbExclamation, "Missing data"
Cell.Select
End Sub
Я запрограммировал его так, чтобы при каждом включении листа выбирался S5
. После того, как пользователь внесет в него изменения, будет выбран C6. Если C6 изменяется, код проверяет, был ли заполнен S5, и направляет пользователя на go, если он все еще пуст. Этот метод может быть расширен, чтобы охватить полную проверку, должны ли быть заполнены все ячейки. Поскольку код теперь является кодом, выбор переходит к следующей ячейке при внесении изменения и в H36 после заполнения S34.