Option Explicit
Dim MatrixFirstCell As Range, MatrixLastCell As Range
Private Function ValidCell(aCell As Range, _
MatrixFirstCell As Range, MatrixLastCell As Range) As Boolean
ValidCell = aCell.Row >= MatrixFirstCell.Row _
And aCell.Column >= MatrixFirstCell.Column _
And aCell.Row <= MatrixLastCell.Row _
And aCell.Column <= MatrixLastCell.Column
End Function
Private Function PrevCell(aCell As Range, _
MatrixFirstCell As Range, MatrixLastCell As Range) As Range
If Not ValidCell(aCell, MatrixFirstCell, MatrixLastCell) Then _
Exit Function
If aCell.Column > MatrixFirstCell.Column Then
Set PrevCell = aCell.Offset(0, -1)
ElseIf aCell.Row = MatrixFirstCell.Row Then
Set PrevCell = Nothing
Else
Set PrevCell = aCell.Parent.Cells(aCell.Row - 1, MatrixLastCell.Column)
End If
End Function
Private Function NextCell(aCell As Range, _
MatrixFirstCell As Range, MatrixLastCell As Range) As Range
If Not ValidCell(aCell, MatrixFirstCell, MatrixLastCell) Then _
Exit Function
If aCell.Column < MatrixLastCell.Column Then
Set NextCell = aCell.Offset(0, 1)
ElseIf aCell.Row = MatrixLastCell.Row Then
Set NextCell = Nothing
Else
Set NextCell = aCell.Parent.Cells(aCell.Row + 1, MatrixFirstCell.Column)
End If
End Function
Private Function PastLastCell(aCell As Range, LastCell As Range)
If aCell Is Nothing Then
PastLastCell = True
Else
PastLastCell = aCell.Row > LastCell.Row _
Or (aCell.Row = LastCell.Row _
And aCell.Column > LastCell.Column)
End If
End Function
Private Function PastFirstCell(aCell As Range, FirstCell As Range)
If aCell Is Nothing Then
PastFirstCell = True
Else
PastFirstCell = aCell.Row < FirstCell.Row _
Or (aCell.Row = FirstCell.Row _
And aCell.Column < FirstCell.Column)
End If
End Function
Private Sub moveLeft(StartCell As Range, EndCell As Range, _
MatrixFirstCell As Range, MatrixLastCell As Range)
'StartCell is "nearer" MatrixFirstCell then EndCell
Dim SrcCell As Range, DestCell As Range
Set DestCell = PrevCell(StartCell, MatrixFirstCell, MatrixLastCell)
If DestCell Is Nothing Then Exit Sub
If Not IsEmpty(DestCell.Value) Then Exit Sub
Set SrcCell = StartCell
Do
Set DestCell = PrevCell(SrcCell, MatrixFirstCell, MatrixLastCell)
SrcCell.Copy DestCell
Set SrcCell = NextCell(SrcCell, MatrixFirstCell, MatrixLastCell)
Loop Until PastLastCell(SrcCell, EndCell)
EndCell.ClearContents
End Sub
Private Sub moveRight(StartCell As Range, EndCell As Range, _
MatrixFirstCell As Range, MatrixLastCell As Range)
'StartCell is "nearer" MatrixLastCell then EndCell
Dim SrcCell As Range, DestCell As Range
Set DestCell = NextCell(StartCell, MatrixFirstCell, MatrixLastCell)
If DestCell Is Nothing Then Exit Sub
If Not IsEmpty(DestCell.Value) Then Exit Sub
Set SrcCell = StartCell
Do
Set DestCell = NextCell(SrcCell, MatrixFirstCell, MatrixLastCell)
SrcCell.Copy DestCell
Set SrcCell = PrevCell(SrcCell, MatrixFirstCell, MatrixLastCell)
Loop Until PastFirstCell(SrcCell, EndCell)
EndCell.ClearContents
End Sub
Private Function updateFirstCell( _
CurrCell As Range, NewCell As Range) As Range
If NewCell.Row < CurrCell.Row Then
Set updateFirstCell = NewCell
ElseIf NewCell.Row = CurrCell.Row And NewCell.Column < CurrCell.Column Then
Set updateFirstCell = NewCell
Else
Set updateFirstCell = CurrCell
End If
End Function
Private Function updateLastCell( _
CurrCell As Range, NewCell As Range) As Range
If NewCell.Row > CurrCell.Row Then
Set updateLastCell = NewCell
ElseIf NewCell.Row = CurrCell.Row And NewCell.Column > CurrCell.Column Then
Set updateLastCell = NewCell
Else
Set updateLastCell = CurrCell
End If
End Function
Private Sub findFirstLastCells(aRng As Range, _
ByRef FirstCell As Range, ByRef LastCell As Range, _
Optional MatrixFirstCell As Range, _
Optional MatrixLastCell As Range)
Dim anArea As Range, aCell As Range
If MatrixLastCell Is Nothing Then _
Set FirstCell = Cells(Rows.Count, Columns.Count) _
Else _
Set FirstCell = MatrixLastCell
If MatrixFirstCell Is Nothing Then _
Set LastCell = Cells(1, 1) _
Else _
Set LastCell = MatrixFirstCell
For Each anArea In aRng.Areas
For Each aCell In anArea.Cells
Set FirstCell = updateFirstCell(FirstCell, aCell)
Set LastCell = updateLastCell(LastCell, aCell)
Next aCell
Next anArea
End Sub
Public Sub Initialize()
findFirstLastCells Selection, MatrixFirstCell, MatrixLastCell
End Sub
Sub moveSelectionRight()
Dim FirstCell As Range, LastCell As Range
If MatrixFirstCell Is Nothing Then
Beep
MsgBox "First, establish the matrix limits by " _
& "selecting it and running the 'Initialize' procedure"
Exit Sub
End If
findFirstLastCells Selection, LastCell, FirstCell, _
MatrixFirstCell, MatrixLastCell
moveRight FirstCell, LastCell, MatrixFirstCell, MatrixLastCell
On Error Resume Next
Application.Union( _
NextCell(FirstCell, MatrixFirstCell, MatrixLastCell), _
NextCell(LastCell, MatrixFirstCell, MatrixLastCell)).Select
End Sub
Sub moveSelectionLeft()
Dim FirstCell As Range, LastCell As Range
If MatrixFirstCell Is Nothing Then
Beep
MsgBox "First, establish the matrix limits by " _
& "selecting it and running the 'Initialize' procedure"
Exit Sub
End If
findFirstLastCells Selection, FirstCell, LastCell, _
MatrixFirstCell, MatrixLastCell
moveLeft FirstCell, LastCell, MatrixFirstCell, MatrixLastCell
On Error Resume Next
Application.Union( _
PrevCell(FirstCell, MatrixFirstCell, MatrixLastCell), _
PrevCell(LastCell, MatrixFirstCell, MatrixLastCell)).Select
End Sub