Scroll By Criteria
- Adjust the constants in the sheet module if necessary.
- I successfully tested the code with two command buttons, but I couldn't get it to work properly with the
SpinUp
and SpinDown
events of the spin button (often it runs the procedures twice, like it has been clicked twice).
- I think it has something to do with focus. While at it, a good idea is to set
TakeFocusOnClick
in the command buttons to False
- The
Select Case
statements should be self explanatory.
The If Statements
- When
Up
is 'used', then at the intersection of one row above the ActiveCell
's row and the criteria column, it checks if the value is equal to criteria. If so, searching up starting from the cell above, tries to find the criteria. If found, scrolls to one row below the found cell and activates the cell in the initially saved column of the ActiveCell
in it. If criteria is not found, it scrolls to the cell defined by the sixth (The header is in the fifth row and five rows are frozen) row and the initially saved column of the ActiveCell
.
- When
Down
is 'used', then at the intersection of one row below the ActiveCell
's row and the criteria column, it checks if the value is equal to criteria. If so, searching down starting from the cell below, tries to find the criteria. If found, scrolls to one row below the found cell and activates the cell in the initially saved column of the ActiveCell
in it. If criteria is not found, it tries to find the criteria searching from the cell one row below to the bottom of the column. If found, , scrolls to one row below the found cell and activates the cell in the initially saved column of the ActiveCell
in it. Otherwise exits the procedure.
The Flow
- The command buttons are 'calling' the procedures
DirUp
or DirDown
, which are calling the changeDirection
procedure which when necessary calls the defineFoundCell
procedure.
Standard Module e.g. Module1
Option Explicit
Sub changeDirection(ByVal Criteria As String, _
Optional ByVal ignoreCase As Boolean = False, _
Optional ByVal ColumnIndex As Variant = 1, _
Optional ByVal FirstRow As Long = 1, _
Optional ByVal goUp As Boolean = False, _
Optional Sheet As Worksheet = Nothing)
' Initialize error handling.
Const ProcName = "changeDirections"
On Error GoTo clearError ' Turn on error trapping.
If Sheet Is Nothing Then
Set Sheet = ActiveSheet
End If
Dim cel As Range
Set cel = Sheet.Cells(ActiveCell.Row, ColumnIndex)
Dim ActiveColumnNumber As Long
ActiveColumnNumber = ActiveCell.Column
Dim rng As Range
Dim ScrollToRow As Long
If goUp Then
Select Case cel.Row
Case Is < FirstRow ' 'ActiveCell' is above 'FirstRow'.
GoTo ProcExit
Case Is = FirstRow ' 'Activecell' is in 'FirstRow'.
GoTo ProcExit
Case Else ' 'ActiveCell' is below 'FirstRow'. Continue...
End Select
If cel.Offset(-1).Value = Criteria Then
defineFoundCell rng, cel.Offset(-2), Criteria, ignoreCase, _
False, FirstRow
Else ' cel.Offset(-1).Value <> Criteria
defineFoundCell rng, cel.Offset(-1), Criteria, ignoreCase, _
False, FirstRow
End If
If rng Is Nothing Then
ScrollToRow = FirstRow
Else
ScrollToRow = rng.Row + 1
End If
Else ' (goDown)
Select Case cel.Row
Case Is < FirstRow ' 'ActiveCell' is above 'FirstRow'.
ScrollToRow = FirstRow
GoTo selectCellRange
Case Is = FirstRow ' 'Activecell' is in 'FirstRow'. Continue...
Case Else ' 'ActiveCell' is below 'FirstRow'. Continue...
End Select
If cel.Offset(1).Value = Criteria Then
ScrollToRow = cel.Row + 2
Else
defineFoundCell rng, cel.Offset(1), Criteria, ignoreCase, _
True, FirstRow
If rng Is Nothing Then
GoTo ProcExit
Else
ScrollToRow = rng.Row + 1
End If
End If
End If
selectCellRange:
Sheet.Cells(ScrollToRow, ActiveColumnNumber).Activate
ActiveWindow.ScrollRow = ScrollToRow
ProcExit:
Exit Sub
clearError:
Debug.Print "'" & ProcName & "': " & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
On Error GoTo 0 ' Turn off error trapping.
GoTo ProcExit
End Sub
Sub defineFoundCell(ByRef FindCellRange As Range, _
InitialCellRange As Range, _
ByVal Criteria As String, _
Optional ByVal ignoreCase As Boolean = False, _
Optional ByVal getAfterInitialCell As Boolean = False, _
Optional ByVal FirstRow As Long = 1, _
Optional ByVal ColumnIndex As Variant = 1)
' Initialize error handling.
Const ProcName = "defineFoundCell"
On Error GoTo clearError ' Turn on error trapping.
Set FindCellRange = Nothing
Dim ws As Worksheet: Set ws = InitialCellRange.Worksheet
Dim FirstCell As Range
Dim LastCell As Range
If getAfterInitialCell Then
Set FirstCell = InitialCellRange
Set LastCell = ws.Cells(ws.Rows.Count, ColumnIndex)
Set FindCellRange = ws.Range(FirstCell, LastCell) _
.Find(What:=Criteria, _
After:=LastCell, _
LookIn:=xlValues, _
LookAt:=xlWhole, _
MatchCase:=Not ignoreCase)
Else ' getAfterInitialCell = False
Set FirstCell = ws.Cells(FirstRow, ColumnIndex)
Set LastCell = InitialCellRange
Set FindCellRange = ws.Range(FirstCell, LastCell) _
.Find(What:=Criteria, _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchDirection:=xlPrevious, _
MatchCase:=Not ignoreCase)
End If
ProcExit:
Exit Sub
clearError:
Debug.Print "'" & ProcName & "': " & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
On Error GoTo 0 ' Turn off error trapping.
GoTo ProcExit
End Sub
Sheet Module e.g. Sheet1
Option Explicit
Private Const Criteria As String = "Extend"
Private Const CriteriaColumnID As Variant = "T" ' or 20
Private Const FirstRow As Long = 6
Sub DirUp()
changeDirection Criteria, , CriteriaColumnID, FirstRow, True, Me
End Sub
Sub DirDown()
changeDirection Criteria, , CriteriaColumnID, FirstRow, , Me
End Sub
Private Sub CommandButton1_Click()
DirUp
End Sub
Private Sub CommandButton2_Click()
DirDown
End Sub
Private Sub SpinButton1_SpinUp()
DirUp
End Sub
Private Sub SpinButton1_SpinDown()
DirDown
End Sub