XL Interpolators
XL Interpolators
XL Interpolators
Option Explicit
' Linear and bilinear inter/extrapolators
' shg 1997-2012
'
'
'
Function
Use
---------- -------LInterp
UDF only
of ranges)
' dLInterp
VBA only
Purpose
------UDF wrapper for dLinterp (linear inter/extrapolation
Linear inter/extrapolator
'
bInterp
VBA only
Interpolates the non-numeric values of a 1D array in
situ
' InterpArr UDF or VBA UDF wrapper for bInterp
' Sub Interpolate
Interpolates the selected range in situ
' Internal functions
' Frac
VBA only
' NumDim
VBA only
As Variant
As Variant
As Long
As Double
' index to rY
' interpolation fraction
As Range
As Range
Dim avdX
Dim avdY
Dim avdZ
As Variant
As Variant
As Variant
se xlErrValue
Set rX = Range(rTbl(1, 2), rTbl(1, rTbl.Columns.Count))
Set rY = Range(rTbl(2, 1), rTbl(rTbl.Rows.Count, 1))
avdX = .Transpose(.Transpose(rX.Value))
avdY = .Transpose(rY.Value)
avdZ = Range(rTbl(2, 2), rTbl(rTbl.Rows.Count, rTbl.Columns.Count)).Valu
e2
BiLInterp = dBiLInterp(x, y, avdX, avdY, avdZ)
End With
Exit Function
Oops:
BiLInterp = CVErr(Err.Number)
End Function
Function dBiLInterp(x As Double, y As Double, _
avdX As Variant, avdY As Variant, _
avdZ As Variant)
' shg 1997-0606, 2007-0307, 2009-0419
'
2009-0615 added support for ascending or descending sort
'
2009-1021 changed implementation of weighted sum
'
2011-1228 fix a bug in computing iMatchType!
' Returns the bilinear interpolation of rTbl with
' o x interpolated across the top row (rX)
' o y interpolated down the left column (rY)
' x and y must be within the upper and lower limits of rX and rY
' rTbl must be sorted
' o
left to right by the top row
' o
top to bottom by the left column
' The sort orders can be ascending or descending,
' each independent of the other.
' All values in rTbl must be numeric (other than the UL corner,
' which is ignored).
Dim
Dim
Dim
Dim
iRow
iCol
dRF
dCF
As
As
As
As
Long
Long
Double
Double
corners
+ 0, iCol
+ 0, iCol
+ 1, iCol
+ 1, iCol
+
+
+
+
0)
1)
0)
1)
*
*
*
*
(1# - dRF)
(1# - dRF)
(dRF - 0#)
(dRF - 0#)
*
*
*
*
(1# - dCF) + _
(dCF - 0#) + _
(1# - dCF) + _
(dCF - 0#)
'===============================================================================
Function bLInterp(avInp As Variant) As Boolean
' shg 2010, 2012
' VBA only
'
'
'
'
' Returns False if avInp is not 1D, or contains fewer than two numbers.
' UDF or VBA
' For example =InterpArr({"", "", 1, "", 3, "", "", 9, ""})
'
returns
{-1, 0, 1, 2, 3, 5, 7, 9, 11}
' Requires NumDim
Dim
Dim
Dim
Dim
Dim
Dim
iLB
iUB
iInp
nNum
aiNum()
iNum
Dim dF
As
As
As
As
As
As
Long
Long
Long
Long
Long
Long
As Double
'
'
'
'
'
'
As Variant
Dim r
As Range
Set r = Application.Caller
If r.Areas.Count > 1 Or (r.Rows.Count > 1 And r.Columns.Count > 1) Then
InterpArray = CVErr(xlErrValue)
Else
With WorksheetFunction
av = avInp
If NumDim(av) > 1 Then av = .Transpose(av)
If NumDim(av) > 1 Then av = .Transpose(av)
If NumDim(av) > 1 Then
InterpArray = CVErr(xlErrValue)
Else
bLInterp av
If r.Rows.Count = 1 Then
InterpArray = av
Else
InterpArray = .Transpose(av)
End If
End If
End With
End If
End Function
Sub Interpolate()
' shg 2012
' Interpolates the selected range in situ
' Requires bLInterp
Dim r
As Range
Dim av
As Variant
If TypeOf Selection Is Range Then
Set r = Selection
If r.Areas.Count > 1 Or (r.Rows.Count > 1 And r.Columns.Count > 1) Then
MsgBox "Must select a single-area, single-row or single-column range
!"
Else
With WorksheetFunction
If r.Rows.Count = 1 Then
av = .Transpose(.Transpose(r.Value))
bLInterp av
r.Value = av
Else
av = .Transpose(r.Value)
bLInterp av
r.Value = .Transpose(av)
End If
End With
End If
Else
MsgBox "Must select a range!"
End If
End Sub