Private requiredCellAddressesArray As Variant ' Declare at the top of the module Private Sub Worksheet_Activate() ' This event fires when the sheet becomes active. ' It's a good place to initialize our array of cell addresses once. If IsEmpty(requiredCellAddressesArray) Then ' Only initialize if not already done Call InitializeRequiredCellsArray End If ' Optional: Ensure the first cell in the sequence is activated when the sheet is activated If Not IsEmpty(requiredCellAddressesArray) Then Me.Range(requiredCellAddressesArray(LBound(requiredCellAddressesArray))).Activate End If End Sub Private Sub InitializeRequiredCellsArray() ' Define your non-contiguous cells in the exact "snake game" order. ' Ensure the order is precise as this defines the user's path. requiredCellAddressesArray = Array("B4", "B5", "B6", "B7", "B8", "B9", "B10", "B11", "B12", "B13", "B14", "B15", "B16", "C16", "D16", _ "E16", "F16", "G16", "G15", "G14", "G13", "G12", "G11", "F11", "E11", "E10", "E9", "E8", "F8", "G8", "H8", "I8", "J8", "J9", "J10", "J11", _ "J12", "J13", "K13", "L13", "M13", "N13", "N12", "N11", "N10", "O10", "P10", "Q10", "Q9", "Q8", "R8", "S8", "S7", "S6", "S5", "R5", "Q5", _ "P5", "O5", "N5", "M5", "M4", "L4", "K4", "J4", "I4", "I5", "H5", "G5", "F5", "F4", "F3", "G3", "G2", "H2", "I2", "J2", "K2", "L2", "M2", "N2", _ "O2", "P2", "Q2", "R2", "R3", "S3", "T3", "U3", "V3", "V4", "V5", "V6", "V7", "V8", "V9", "W9", "X9", "X8", "X7", "Y7", "Y6", "Y5", "Y4", "X4", _ "X3", "X2", "Y2", "Z2", "AA2", "AA3", "AA4", "AA5", "AA6", "AA7", "AA8", "AA9", "AA10", "Z10", "Z11", "Z12", "Z13", "Z14", "Z15", "Y15", "X15", _ "W15", "V15", "U15", "U16", "T16", "S16", "R16", "Q16", "P16", "O16", "N16", "M16") End Sub Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim currentCellAddress As String Dim previousCellAddressInSequence As String ' Renamed for clarity Dim currentCellIndexInArray As Long ' Renamed for clarity Dim i As Long Dim blnTargetIsInRequiredPath As Boolean Dim rngPreviousCell As Range ' To hold the actual Range object of the previous cell ' Turn off events to prevent re-triggering this macro during our own actions Application.EnableEvents = False On Error GoTo CleanUp If IsEmpty(requiredCellAddressesArray) Then ' Ensure array is initialized Call InitializeRequiredCellsArray End If ' 1. Determine if the selected cell (Target) is part of our required path blnTargetIsInRequiredPath = False currentCellIndexInArray = -1 ' Initialize to not found For i = LBound(requiredCellAddressesArray) To UBound(requiredCellAddressesArray) ' Compare the full address to ensure exact match (e.g., $A$1 vs $A$1) If Target.Address = Me.Range(requiredCellAddressesArray(i)).Address Then currentCellIndexInArray = i blnTargetIsInRequiredPath = True Exit For End If Next i ' 2. Handle invalid selections (multi-cell or outside the path) If Not blnTargetIsInRequiredPath Or Target.Cells.Count > 1 Then Dim firstEmptyRequiredCell As Range ' Holds the Range object of the first empty cell firstEmptyRequiredCellIndex = -1 ' Find the first empty cell in the defined sequence For i = LBound(requiredCellAddressesArray) To UBound(requiredCellAddressesArray) Set firstEmptyRequiredCell = Me.Range(requiredCellAddressesArray(i)) If IsEmpty(firstEmptyRequiredCell.Value) Or Trim(firstEmptyRequiredCell.Value) = "" Then firstEmptyRequiredCellIndex = i Exit For End If Next i ' If there's an empty required cell, activate it and warn the user If firstEmptyRequiredCellIndex <> -1 Then MsgBox "Please fill in all preceding mandatory fields. Cell " & firstEmptyRequiredCell.Address(False, False) & " is blank.", vbExclamation, "Mandatory Field" firstEmptyRequiredCell.Activate Else ' All required cells are filled, allow movement freely outside the path. ' No action needed, user can move elsewhere. End If ' 3. Handle valid single cell selection within the required path Else ' User selected a designated single cell in the sequence ' Check if the immediately preceding cell IN THE SEQUENCE is filled If currentCellIndexInArray > LBound(requiredCellAddressesArray) Then ' Get the address of the actual previous cell in the defined sequence previousCellAddressInSequence = requiredCellAddressesArray(currentCellIndexInArray - 1) Set rngPreviousCell = Me.Range(previousCellAddressInSequence) ' Check if that specific previous cell is empty If IsEmpty(rngPreviousCell.Value) Or Trim(rngPreviousCell.Value) = "" Then MsgBox "Please fill in cell " & rngPreviousCell.Address(False, False) & " before moving to " & Target.Address(False, False) & ".", vbExclamation, "Mandatory Field" rngPreviousCell.Activate ' Force user back to the unfilled previous cell End If End If ' Additionally, ensure no cells earlier in the sequence were skipped ' This catches cases where they fill the immediate previous, but skipped one even earlier. For i = LBound(requiredCellAddressesArray) To currentCellIndexInArray - 1 Set currentCell = Me.Range(requiredCellAddressesArray(i)) ' Using currentCell to iterate through preceding If IsEmpty(currentCell.Value) Or Trim(currentCell.Value) = "" Then MsgBox "Please fill in all preceding mandatory fields. Cell " & currentCell.Address(False, False) & " is blank.", vbExclamation, "Mandatory Field" currentCell.Activate ' Go back to the first skipped cell Exit For ' Stop checking once the first skipped cell is found End If Next i End If CleanUp: Application.EnableEvents = True If Err.Number <> 0 Then MsgBox "An error occurred: " & Err.Description, vbCritical, "Error" End If End Sub