Sorting And Ordering Worksheets In A Workbook
This page describes VBA procedures you can use to sort or order worksheets within a workbook.
Excel does not provide a mechanism or command to sort or otherwise order worksheets within a workbook. This article provides 
a number of VBA functions that you can use to sort or reorder worksheets. With these functions, you can 
- Sort some or all worksheet by name, in either ascending or descending  order.
 
- Order the worksheets by the names provided in an array.
 
- Order the worksheets in either ascending or descending order based on a cell reference in each worksheet.
 
- Group worksheet by tab color (Excel 2002 and later only).
 
- Order worksheets based on sheet names in a range of cells.
 
The functions are presented below. You can 
download a a bas module file containing
all the code on this page. The code on this page consists of functions that take parameters to control their behavior. You should 
create procedures that prompt the user for the worksheet names to sort and then 
call the procedures on this page from those procedures. 

This function allows you to sort some or all worksheets based on their names, in either ascending or descending order.  You also have 
the option of specifying whether to sort numeric sheet names as numbers or as text. For example, the following are numeric sheet names
sorted as text: 11, 115, 22. Sorted as numeric, the order would be 11, 22,115.  If you omit the Numeric parameter,
it is treated as False and the sort will use a text value sort rather than numeric value sort. If this parameter is True, all of the sheets
that are to be sorted must have a numeric name. Otherwise, the function will quit with a result of False. The function declaration is:
Public Function SortWorksheetsByName(ByVal FirstToSort As Long, ByVal LastToSort As Long, _
    ByRef ErrorText As String, Optional ByVal SortDescending As Boolean = False) As Boolean
FirstToSort is the index (position) of the first worksheet to sort.
LastToSort is the index (position) of the laset worksheet to sort. If either both 
FirstToSort and LastToSort are less than or equal to 0, all sheets in the
workbook are sorted.
ErrorText is a variable that will receive the text description of any error that may occur.
SortDescending is an optional parameter to indicate that the sheets should be sorted in descending 
order. If True, the sort is in descending order. If omitted or False, the 
sort is in ascending order.
The function returns True if successful. If an error occurs, the function returns False
and the variable ErrorText is set to the text of the error message.
The code for SortWorksheetsByName is shown below.
Public Function SortWorksheetsByName(ByVal FirstToSort As Long, _
                            ByVal LastToSort As Long, _
                            ByRef ErrorText As String, _
                            Optional ByVal SortDescending As Boolean = False, _
                            Optional ByVal Numeric As Boolean = False) As Boolean
Dim M As Long
Dim N As Long
Dim WB As Workbook
Dim B As Boolean
Set WB = Worksheets.Parent
ErrorText = vbNullString
If WB.ProtectStructure = True Then
    ErrorText = "Workbook is protected."
    SortWorksheetsByName = False
End If
    
If (FirstToSort = 0) And (LastToSort = 0) Then
    FirstToSort = 1
    LastToSort = WB.Worksheets.Count
Else
    
    B = TestFirstLastSort(FirstToSort, LastToSort, ErrorText)
    If B = False Then
        SortWorksheetsByName = False
        Exit Function
    End If
End If
If Numeric = True Then
    For N = FirstToSort To LastToSort
        If IsNumeric(WB.Worksheets(N).Name) = False Then
            ' can't sort non-numeric names
            ErrorText = "Not all sheets to sort have numeric names."
            SortWorksheetsByName = False
            Exit Function
        End If
    Next N
End If
For M = FirstToSort To LastToSort
    For N = M To LastToSort
        If SortDescending = True Then
            If Numeric = False Then
                If StrComp(WB.Worksheets(N).Name, WB.Worksheets(M).Name, vbTextCompare) > 0 Then
                    WB.Worksheets(N).Move before:=WB.Worksheets(M)
                End If
            Else
                If CLng(WB.Worksheets(N).Name) > CLng(WB.Worksheets(M).Name) Then
                    WB.Worksheets(N).Move before:=WB.Worksheets(M)
                End If
            End If
        Else
            If Numeric = False Then
                If StrComp(WB.Worksheets(N).Name, WB.Worksheets(M).Name, vbTextCompare) < 0 Then
                    WB.Worksheets(N).Move before:=WB.Worksheets(M)
                End If
            Else
                If CLng(WB.Worksheets(N).Name) < CLng(WB.Worksheets(M).Name) Then
                    WB.Worksheets(N).Move before:=WB.Worksheets(M)
                End If
            End If
        End If
    Next N
Next M
SortWorksheetsByName = True
End Function

The SortWorksheetByNameArray function sorts the worksheets in the order of the names passed as 
n array. While the individual elements of the array need not refer to adjacent worksheets, the worksheets, taken as a group, 
named by the values in the arrray, must be adjacent. You cannot sort non-adjacent sheets. The function returns True
if successful or False if an error occurred. If an error occurred, the variable ErrorText
will contain the text of the error message.
The declaration of SortWorksheetsByNameArray declaration is shown below:
Public Function SortWorksheetsByNameArray(NameArray() As Variant, ByRef ErrorText As String) As Boolean
NameArray is an array containing the worksheet names in the order that they should be ordered.
The code for SortWorksheetsByNameArray is shown below:
Public Function SortWorksheetsByNameArray(NameArray() As Variant, ByRef ErrorText As String) As Boolean
Dim Arr() As Long
Dim N As Long
Dim M As Long
Dim L As Long
Dim WB As Workbook
ErrorText = vbNullString
ReDim Arr(LBound(NameArray) To UBound(NameArray))
On Error Resume Next
For N = LBound(NameArray) To UBound(NameArray)
    
    Err.Clear
    M = Len(WB.Worksheets(NameArray(N)).Name)
    If Err.Number <> 0 Then
        ErrorText = "Worksheet does not exist."
        SortWorksheetsByNameArray = False
        Exit Function
    End If
    
    If Arr(N) > 0 Then
        ErrorText = "Duplicate worksheet name in NameArray."
        SortWorksheetsByNameArray = False
        Exit Function
    End If
        
    Arr(N) = Worksheets(NameArray(N)).Index
Next N
For M = LBound(Arr) To UBound(Arr)
    For N = M To UBound(Arr)
        If Arr(N) < Arr(M) Then
            L = Arr(N)
            Arr(N) = Arr(M)
            Arr(M) = L
        End If
    Next N
Next M

The GroupSheetsByColor function groups sheets by their tab color (available only in Excel 2002 and later).
You specify in an array the colors and the order in which those colors should appear. The sheets are grouped according to those
color indicators. The color indicators are the ColorIndex values, not actual RGB colors. The declaration for 
GroupSheetsByColor is shown below:
Public Function GroupSheetsByColor(ByVal FirstToSort As Long, ByVal LastToSort As Long, _
    ByRef ErrorText As String, ColorArray() As Long) As Boolean
FirstToSort is the index (position) number of the first sheet to sort.
LastToSort is the index (position) number of the last sheet to sort. If both FirstToSort
and LastSheetToSort are less than or equal to 0, all sheets are sorted. 
ErrorText is a variable that will contain the error message if an error occurs.
ColorArray is an array of longs indicating the colors and order in which the sheets should be grouped.
The code is shown below:
Public Function GroupSheetsByColor(ByVal FirstToSort As Long, ByVal LastToSort As Long, _
    ByRef ErrorText As String, ColorArray() As Long) As Boolean
Dim WB As Workbook
Dim B As Boolean
Dim N1 As Long
Dim N2 As Long
Dim N3 As Long
Dim CI1 As Long
Dim CI2 As Long
Dim CArray As Variant
Dim CNdx1 As Long
Dim Cndx2 As Long
Const MIN_COLOR_INDEX = 1
Const MAX_COLOR_INDEX = 56
If IsArrayAllocated(ColorArray) = False Then
    ErrorText = "ColorArray is not a valid, allocated array."
    GroupSheetsByColor = False
    Exit Function
End If
Set WB = Worksheets.Parent
ErrorText = vbNullString
If IsMissing(ColorArray) = False Then
    If IsArray(ColorArray) = False Then
        ErrorText = "ColorArray is not an array"
        GroupSheetsByColor = False
        Exit Function
    End If
Else
    
    For N1 = LBound(ColorArray) To UBound(ColorArray)
        If (ColorArray(N1) > MAX_COLOR_INDEX) Or (ColorArray(N1) < MIN_COLOR_INDEX) Then
            ErrorText = "Invalid ColorIndex in ColorArray"
            GroupSheetsByColor = False
            Exit Function
        End If
    Next N1
End If
Set WB = Worksheets.Parent
ErrorText = vbNullString
If (FirstToSort <= 0) And (LastToSort <= 0) Then
    FirstToSort = 1
    LastToSort = WB.Worksheets.Count
End If
B = TestFirstLastSort(FirstToSort, LastToSort, ErrorText)
If B = False Then
    GroupSheetsByColor = False
    Exit Function
End If
For N1 = FirstToSort To LastToSort
    If WB.Worksheets(N1).Tab.ColorIndex = ColorArray(LBound(ColorArray)) Then
        WB.Worksheets(N1).Move before:=WB.Worksheets(1)
        Exit For
    End If
Next N1
N3 = 1
For N2 = LBound(ColorArray) To UBound(ColorArray)
    For N1 = 2 To LastToSort
        If WB.Worksheets(N1).Tab.ColorIndex = ColorArray(N2) Then
            WB.Worksheets(N1).Move after:=WB.Worksheets(N3)
            N3 = N3 + 1
        End If
        
    Next N1
Next N2
GroupSheetsByColor = True
End Function

The following functions are used by the primary functions on this page.
Private Function ArrayElementsInOrder(Arr As Variant, _
    Optional Descending As Boolean = False, _
    Optional Diff As Integer = 0) As Boolean
Dim N As Long
For N = LBound(Arr) To UBound(Arr) - 1
    If Descending = False Then
        If Diff > 0 Then
            If Arr(N) <> Arr(N + 1) - Diff Then
                ArrayElementsInOrder = False
                Exit Function
            End If
        Else
            If Arr(N) > Arr(N + 1) Then
                ArrayElementsInOrder = False
                Exit Function
            End If
        End If
    Else
        If Diff > 0 Then
            If Arr(N) <> Arr(N + 1) + Diff Then
                ArrayElementsInOrder = False
                Exit Function
            End If
        Else
            If Arr(N) < Arr(N + 1) Then
                ArrayElementsInOrder = False
                Exit Function
            End If
        End If
    End If
Next N
ArrayElementsInOrder = True
End Function
Private Function TestFirstLastSort(FirstToSort As Long, LastToSort As Long, _
    ByRef ErrorText As String) As Boolean
ErrorText = vbNullString
If FirstToSort <= 0 Then
    TestFirstLastSort = False
    ErrorText = "FirstToSort is less than or equal to 0."
    Exit Function
End If
If FirstToSort > Worksheets.Count Then
    TestFirstLastSort = False
    ErrorText = "FirstToSort is greater than number of sheets."
    Exit Function
End If
If LastToSort <= 0 Then
    TestFirstLastSort = False
    ErrorText = "LastToSort is less than or equal to 0."
    Exit Function
End If
If LastToSort > Worksheets.Count Then
    TestFirstLastSort = False
    ErrorText = "LastToSort greater than number of sheets."
    Exit Function
End If
If FirstToSort > LastToSort Then
    TestFirstLastSort = False
    ErrorText = "FirstToSort is greater than LastToSort."
    Exit Function
End If
    
TestFirstLastSort = True
End Function
Private Function IsArrayAllocated(Arr As Variant) As Boolean
    On Error Resume Next
    Dim V As Variant
    IsArrayAllocated = True
    V = Arr(LBound(Arr, 1))
    If IsError(V) = True Then
        IsArrayAllocated = False
    End If
    If (UBound(Arr, 1) < LBound(Arr, 1)) Then
        IsArrayAllocated = False
    End If
    
End Function
Private Function SheetExists(WSName As String, Optional WB As Workbook = Nothing) As Boolean
On Error Resume Next
SheetExists = IsError(IIf(WB Is Nothing, ActiveWorkbook, WB).Worksheets(WSName)) = False
End Function
You can download a a bas module file containing
all the code on this page.
This page last updated: 22-September-2007