Information About Series Of Numbers
This page describes a few VBA methods for working with a series of numbers.
It is a common task in Excel to work with sequential series of data. This page contain a number of VBA functions that can
be used to get information about a series of numbers. All the VBA code on this page requires that the data be in a single
column, in sorted order, with no non-numeric or blank elements within the series.
All of the examples here will assume that the range A1:A7 contains the numbers:
1
4
9
10
11
16
20
You can download a bas file containing the
functions shown below.
The procedure ListSeriesBlocks looks at a series of numbers in ascending sorted order and
writes out to a range the present and missing blocks of data. You can specify the increment between sequential numbers. For example,
given input data above, the code will write out the following, beginning in the cell referred to by Dest:
Present 1 4
Missing 5 8
Present 9 11
Missing 12 15
Present 16 16
Missing 17 19
Present 20 20
which lists the groups of numbers that are present and missing in the list. The
output data always begins with a "Present" row, since it is assumed that no data
is missing before the beginning of the list, alternates between "Present" and
"Missing" elements, and always ends with a "Present" element, since it is
assumed that no data is missing past the end of the list.
The
VBA code is shown below. Change the lines marked with to your requirements.
Sub ListSeriesBlocks()
Dim StartRow As Long
Dim EndRow As Long
Dim Temp As Long
Dim RowNdx As Long
Dim Dest As Range
Dim DataColumn As String
Dim WS As Worksheet
Dim SaveStart As Long
Dim DataIncrement As Long
StartRow = 1
DataColumn = "A"
Set WS = Worksheets("Sheet1")
Set Dest = Worksheets("Sheet2").Range("A1")
DataIncrement = 1
With WS
EndRow = .Cells(.Rows.Count, DataColumn).End(xlUp).Row
SaveStart = .Cells(StartRow, DataColumn)
For RowNdx = StartRow + 1 To EndRow
If .Cells(RowNdx, DataColumn) + DataIncrement <> _
.Cells(RowNdx + 1, DataColumn)
Then
Dest(1, 1) = "Present"
Dest(1, 2) = SaveStart
Dest(1, 3) = .Cells(RowNdx, DataColumn).Value
Set Dest = Dest(2, 1)
If RowNdx <= EndRow - 1 Then
Dest(1, 1) = "Missing"
Dest(1, 2) = .Cells(RowNdx, DataColumn).Value + DataIncrement
Dest(1, 3) = .Cells(RowNdx + 1, DataColumn).Value - DataIncrement
SaveStart = .Cells(RowNdx + 1, DataColumn).Value
End If
Set Dest = Dest(2, 1)
End If
Next RowNdx
End With
End Sub
As
shown in the image to the left, the data is in the range D11:D20 and the
expected increment between adjacent cells is specified in cell D10 (value of 5).
The formula, entered in E11 and filled down to E20,
=IF(ROW()=ROW($E$11),"OK",IF(OFFSET(D11,-1,0,1,1)=OFFSET(D11,0,0,1,1)-$D$10,"OK",OFFSET(D11,-1,0,1,1)+$D$10&"
-> "&OFFSET(D11,0,0,1,1)-$D$10))
will return a value of either "OK" if the row is the
specified increment greater than the cell above it (e.g., 40 and 45 in the
example), or an indication of missing element (e.g., 70 -> 80 indicating the
missing numbers between the existing element 65 and 85). Note that the formula
above should be entered with out any line breaks.
The IsSeriesSorted returns True or False indicating whether the series referred to by SeriesRange is
in sorted order, either ascending or descending, as specified by the Ascending parameter.
Function IsSeriesSorted(SeriesRange As Range, _
Optional Ascending As Boolean =
True) As Boolean
Dim StartRow As Long
Dim EndRow As Long
Dim RowNdx As Long
Dim ColNum As Long
Dim V1 As Double
Dim V2 As Double
If SeriesRange.Columns.Count > 1 Then
IsSeriesSorted = False
Exit Function
End If
StartRow = SeriesRange.Cells(1, 1).Row
With SeriesRange
EndRow = .Cells(.Cells.Count).Row
End With
ColNum = SeriesRange.Cells(1, 1).Column
With SeriesRange.Worksheet
For RowNdx = StartRow To EndRow - 1
If IsNumeric(.Cells(RowNdx,
ColNum).Value) = False Then
IsSeriesSorted = False
Exit Function
End If
V1 = .Cells(RowNdx, ColNum).Value
V2 = .Cells(RowNdx + 1, ColNum).Value
If Ascending = True Then
If V1 > V2 Then
IsSeriesSorted = False
Exit Function
End If
Else
If V1 < V2 Then
IsSeriesSorted = False
Exit Function
End If
End If
Next RowNdx
End With
IsSeriesSorted = True
End Function
You can use a formula to test whether a series is sorted. With data in
F11:F20, the following formula will test whether that data is in ascending
sorted order:
=IF(SUM(IF(F12:F20-F11:F19>=0,0,1))=0,"SORTED","UNSORTED")
The following formula will test whether the same data is in descending
sorted order:
=IF(SUM(IF(F12:F20-F11:F19<=0,0,1))=0,"SORTED","UNSORTED")
These formulas may be combined to test whether the data is sorted in either
ascending or descending order:
=IF(OR(SUM(IF(F12:F20-F11:F19>=0,0,1))=0,SUM(IF(F12:F20-F11:F19<=0,0,1))=0),"SORTED","UNSORTED")
All of these formulas are Array Formulas, which means that
you must press CTRL+SHIFT+ENTER rather than just
ENTER when you
first enter the formula and whenever you edit it later. If you do this
properly, Excel will display the formula enclosed in curly braces
{ }.
The MaxDifferenceInSeries returns the maximum difference between two adjacent elements
in a series. SeriesRange must be a sorted single column
of numeric values. The function will return -1 if invalid data is found.
Function MaxDifferenceInSeries(SeriesRange As Range, _
Optional Ascending As Boolean = True) As Double
Dim StartRow As Long
Dim EndRow As Long
Dim RowNdx As Long
Dim ColNum As Long
Dim V1 As Double
Dim V2 As Double
Dim MaxDiff As Double
If SeriesRange.Columns.Count > 1 Then
MaxDifferenceInSeries = False
Exit Function
End If
StartRow = SeriesRange.Cells(1, 1).Row
With SeriesRange
EndRow = .Cells(.Cells.Count).Row
End With
ColNum = SeriesRange.Cells(1, 1).Column
With SeriesRange.Worksheet
For RowNdx = StartRow To EndRow - 1
If IsNumeric(.Cells(RowNdx,
ColNum)) = False Then
MaxDifferenceInSeries = -1
Exit Function
End If
V1 = .Cells(RowNdx, ColNum).Value
V2 = .Cells(RowNdx + 1, ColNum).Value
If Ascending = True Then
If V1 > V2 Then
MaxDifferenceInSeries =
-1
Exit Function
End If
If (V2 - V1) >
MaxDiff Then
MaxDiff = V2 - V1
End If
Else
If V1 < V2 Then
MaxDifferenceInSeries =
-1
Exit Function
End If
If (V1 - V2) > MaxDiff Then
MaxDiff = V1 - V2
End If
End If
Next RowNdx
MaxDifferenceInSeries = MaxDiff
End With
End Function
The MinDifferenceInSeries returns the minimum difference between two adjacent elements
in a series. SeriesRange must be a sorted single column
of numeric values. The function will return -1 if invalid data is found.
Function MinDifferenceInSeries(SeriesRange As Range, _
Optional Ascending As Boolean = True) As Double
Dim StartRow As Long
Dim EndRow As Long
Dim RowNdx As Long
Dim ColNum As Long
Dim V1 As Double
Dim V2 As Double
Dim MinDiff As Double
If SeriesRange.Columns.Count > 1 Then
MinDifferenceInSeries = False
Exit Function
End If
StartRow = SeriesRange.Cells(1, 1).Row
With SeriesRange
EndRow = .Cells(.Cells.Count).Row
End With
ColNum = SeriesRange.Cells(1, 1).Column
On Error Resume Next
Err.Clear
With Application.WorksheetFunction
MinDiff
= .Max(SeriesRange) - .Min(SeriesRange)
If Err.Number <> 0 Then
MinDifferenceInSeries = -1
Exit Function
End If
End With
With SeriesRange.Worksheet
For RowNdx = StartRow To EndRow - 1
If IsNumeric(.Cells(RowNdx, ColNum)) = False Then
MinDifferenceInSeries = -1
Exit Function
End If
V1 = .Cells(RowNdx, ColNum).Value
V2 = .Cells(RowNdx + 1, ColNum).Value
If Ascending = True Then
If V1 > V2 Then
MinDifferenceInSeries =
-1
Exit Function
End If
If (V2 - V1) < MinDiff Then
MinDiff = V2 - V1
End If
Else
If V1 < V2 Then
MinDifferenceInSeries =
-1
Exit Function
End If
If (V1 - V2) < MinDiff Then
MinDiff = V1 - V2
End If
End If
Next RowNdx
MinDifferenceInSeries = MinDiff
End With
End Function
You can download a bas file containing the funcitons shown above.
You can use an array formula to determine the
minimum and maximum differences between adjacent elements in a series of
numbers.
To get the minimum increment between the numbers in D11:D20, use
=MIN(ABS(D11:D19-D12:D20))
To get the maximum increment between the numbers in D11:D20, use
=MAX(ABS(D11:D19-D12:D20))
Both of these formulas are array formulas, and therefore you must press
CTRL+SHIFT+ENTER rather than just
ENTER when you first enter the formula
and whenever you edit it later. If you do this properly, Excel will
display the formula enclosed in curly braces {
}.
You can read more about array formulas here.
This page last udpated: 13-July-2007