| |
The procedure declaration follows: Function InsertAndFillMissingNumbers(RangeToTest As Range, FillStep As Double, _
Optional FullRows As Boolean = False) As Range
where
RangeToTest is the range containing the actual values themselves, not
the range into which the series will be expanded. In the picture on the far
left above, the RangeToTest in D1:D6. RangeToTest must be a range with
a single column. The function will terminate if RangeToTest contains more
than one column. The cells in RangeToTest must be non-blank, numeric, and be
in ascending order. RangeToTest may be a single cell, but in this case
nothing will happen. The result of the function will be the same range as
RangeToTest.
FillStep is the increment to use when filling
the inserted cells. The existing values in the RangeToTest must be integer
multiples of FillStep. FillStep may be a fractional number, such as
1.5. If the existing values are not integer multiples of FillStep, the
results are undefined.
FullRows indicates whether to insert entire
rows or just cells in the column. If FullRows is omitted or False, then only
cells within the column of RangeToTest are inserted. If FullRows is True,
entire rows are inserted.
If all the parameters are correct and the RangeToTest
is proper, then the function will return a Range object referring to the
expanded range. In the example above, the result of the function is the
range D1:D10. If an error occurs, the function returns Nothing.
The complete code is shown below:
Function InsertAndFillMissingNumbers(RangeToTest As Range, FillStep As Double, _
Optional FullRows As Boolean = False) As Range
Dim BottomRow As Long
Dim TopRow As Long
Dim NumToInsert As Long
Dim RowNdx As Long
Dim WS As Worksheet
Dim ColNum As Long
Dim StartRng As Range
Dim EndRng As Range
Dim Rng As Range
''''''''''''''''''''''''''''''
' Ensure RangeToTest is not
' nothing.
''''''''''''''''''''''''''''''
If RangeToTest Is Nothing Then
Exit Function
End If
'''''''''''''''''''''''''''''''''''''
' Ensure RangeToTest is a single
' column.
'''''''''''''''''''''''''''''''''''''
If RangeToTest.Columns.Count > 1 Then
Exit Function
End If
''''''''''''''''''''''''''''''''''''
' Ensure that there is at least
' one non-blank cell in RangeToTest.
''''''''''''''''''''''''''''''''''''
If Application.WorksheetFunction.Count(RangeToTest) = 0 Then
Exit Function
End If
'''''''''''''''''''''''''''''''''''''
' Ensure that all cell values are
' numeric and not blank.
'''''''''''''''''''''''''''''''''''''
For Each Rng In RangeToTest.Cells
If Rng.Value = vbNullString Then
Exit Function
End If
If IsNumeric(Rng.Value) = False Then
Exit Function
End If
Next Rng
'''''''''''''''''''''''''''''''''''
' Set some variable values.
'''''''''''''''''''''''''''''''''''
With RangeToTest
Set WS = .Worksheet
Set StartRng = .Cells(1, 1)
Set EndRng = .Cells(.Cells.Count)
TopRow = .Cells(1, 1).Row
BottomRow = .Cells(.Cells.Count).Row
ColNum = .Column
End With
''''''''''''''''''''''''''''''
' If the bottom cell is empty
' move it up to the last
' non-blank cell.
''''''''''''''''''''''''''''''
With WS
If .Cells(BottomRow, ColNum).Value = vbNullString Then
BottomRow = .Cells(BottomRow, ColNum).End(xlUp).Row
End If
End With
''''''''''''''''''''''''''''''''''''''''''''''
' Loop RowNdx from the bottom cell upwards,
' with a step of -1.
''''''''''''''''''''''''''''''''''''''''''''''
For RowNdx = BottomRow To (TopRow + 1) Step -1
With WS
If .Cells(RowNdx, ColNum).Value - FillStep <> .Cells(RowNdx - 1, ColNum).Value Then
''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' The Cell value - FillStep is not equal to the value
' of the cell above it. We need to insert one or more
' rows. Compute the number of rows to insert. Note that
' the division at the end of this line is integer
' division ( the \ operator, not the / operator).
''''''''''''''''''''''''''''''''''''''''''''''''''''''''
NumToInsert = (Abs(.Cells(RowNdx, ColNum).Value - .Cells(RowNdx - 1, ColNum).Value) - FillStep) \ FillStep
If NumToInsert <> 0 Then
If FullRows = True Then
''''''''''''''''''''''''''''''''''''''
' Insert complete rows.
''''''''''''''''''''''''''''''''''''''
.Rows(RowNdx).Resize(NumToInsert).Insert
Else
'''''''''''''''''''''''''''''''''''''''
' Insert only cells in the RangeToTest
' column.
'''''''''''''''''''''''''''''''''''''''
.Cells(RowNdx, ColNum).Resize(NumToInsert).Insert shift:=xlDown
End If
''''''''''''''''''''''''''''''''''''''''''''''
' Put the next value in the first inserted
' cell. Then user DataSerise to fill down
' the rest of the new values.
''''''''''''''''''''''''''''''''''''''''''''''
.Cells(RowNdx, ColNum).Value = .Cells(RowNdx - 1, ColNum) + FillStep
.Cells(RowNdx, ColNum).Resize(NumToInsert, 1).DataSeries rowcol:=xlColumns, Type:=xlLinear, Step:=FillStep
End If
End If
End With
Next RowNdx
''''''''''''''''''''''''''''''''''''''
' Return the result range. EndRng
' was set to the bottom of RangeToTest
' and was moved down as a result of the
' inserts, so it is now at the end of
' the expanded range.
'''''''''''''''''''''''''''''''''''''''
Set InsertAndFillMissingNumbers = Range(StartRng, EndRng)
End Function
Finding A Series That
Sums To A Specific Value
The procedure below is only tangentially related to
previous topic on this page, but I couldn't think where else to put it. This
procedure will find a contiguous range of cells in column A that sum to the
value in cell B1. It will scan down column A until it finds a set of
contiguous cells that sum to the value in B1 or until a blank cell is
encountered in column A, in which case there is no series that sums to the
value in B1. If there is more than one series that sums to B1, only the
first such series is found. The range of the series, if found, is
highlighted.
Sub FindSeries()
Dim StartRng As Range
Dim EndRng As Range
Dim Answer As Long
Dim TestTotal As Long
Answer = Range("B1") '<<< CHANGE
Set StartRng = Range("A1")
Set EndRng = StartRng
Do Until False
TestTotal = Application.Sum(Range(StartRng, EndRng))
If TestTotal = Answer Then
Range(StartRng, EndRng).Select
Exit Do
ElseIf TestTotal > Answer Then
Set StartRng = StartRng(2, 1)
Set EndRng = StartRng
Else
Set EndRng = EndRng(2, 1)
If EndRng.Value = vbNullString Then
MsgBox "No series found"
Exit Do
End If
End If
Loop
End Sub
Testing If A
Column Of Numbers Is A Valid Series
You can use the formula below to determine if all the
entries in a specified range are in the correct series order. That is,
whether they are equally spaced, with a specified step increment. In the
formula, TheRange
is the range of cells to test, and
Step
is the correct increment between items N and N+1 of the series, going
downward in the column of numbers. The formula will return 0 if all the
items are separated by the value of
Step.
For example, if A1:A5 is 2, 4, 6, 8, 10 and Step is 2, the result is 0,
indicating that all values are separated by
Step.
If A1:A5 is 2, 5, 8, 10, 12, the result is 2, indicating that, moving
downwards, 2 items (5 and 8 in this example) are not separated by
Step.
The Step
increment should be positive for series in ascending order or negative for
series in descending order.
This is an array formula, so you must press
CTRL+SHIFT+ENTER rather than just ENTER after you type the formula and
whenever you edit it later. If you do this properly, Excel will display the
formula enclosed in curly braces { } in the formula bar. Click
here for more information about working with array
formulas.
Note that the formula is split in to two lines
here for display purposes. When copied to Excel, the formula should be a
single line.
=SUM(IF(OFFSET(TheRange,1,0,ROWS(TheRange)-1,1)=
OFFSET(TheRange,0,0,ROWS(TheRange)-1,1)+Step,0,1))
If you prefer to use cell references instead of a
defined name, use a formula like
=SUM(IF(A2:A10=A1:A9+B1,0,1))
where
A1:A10 contains the value to be test and
B1
contains the Step value. Note that the first range is
A2:A10
and second range is A1:A9.
Like the previous formula, this formula must be entered with
CTRL+SHIFT+ENTER rather than just ENTER. |
|