Public Function LOOKUPX(X As Single, XRange As Range, ValueRange As Range, _
Optional XLog As Boolean, Optional ErrMsg As String)
'
' User-defined function for 1 dimensional table lookup with interpolation.
'
' Written (or more likely "found") Mar-2002.
' Revised September 2014 to allow the X range and Value range to be non-adjacent to one another, and to allow the X values
' to be sorted as either ascending or descending.
'
' Arguments:
' X - The table coordinate where the answer is needed.
' XRange - The range of x values.
' ValueRange - The range for the values to be interpolated in the table.
' XLog - 0 for linear interpolation, 1 for logarithmic.
' ErrMsg - Optional string variable that will be displayed on errors.
'
' The designation of the direction for x is arbitrary. Either will work.
' The X values must be sorted, but they can be sorted ascending or descending.
'
On Error GoTo ErrorHandler ' Enable error-handling routine.
'
Dim DeltaX As Double, FX0 As Double, FX1 As Double, X0 As Double, X1 As Double, _
X0Pos As Double, X1Pos As Double, XTable As Range, XFlag As Boolean
'
' Assign values to optional argument
'
If IsMissing(XLog) Then
XLog = False
End If
'
' Determine column or row orientation of XRange &
' Determine if XRange is sorted ascending or descending &
' Find bracketing value positions in the table &
' Find bracketing x values and function values.
' If X is out of range, add to error message and exit function.
'
If XRange.Column < ValueRange.Column Then
If Application.WorksheetFunction.Index(XRange, 2, 1) > Application.WorksheetFunction.Index(XRange, 1, 1) Then
X0Pos = Application.WorksheetFunction.Match(X, XRange, 1)
Else
X0Pos = Application.WorksheetFunction.Match(X, XRange, -1)
End If
If XRange.Count = X0Pos Then
XFlag = True
X1Pos = X0Pos
Else
X1Pos = 1 + X0Pos
End If
X0 = Application.WorksheetFunction.Index(XRange, X0Pos, 1)
FX0 = Application.WorksheetFunction.Index(ValueRange, X0Pos, 1)
X1 = Application.WorksheetFunction.Index(XRange, X1Pos, 1)
FX1 = Application.WorksheetFunction.Index(ValueRange, X1Pos, 1)
If Application.WorksheetFunction.Index(XRange, 2, 1) > Application.WorksheetFunction.Index(XRange, 1, 1) And X > X1 Then
ErrMsg = "Data Out of Range " & ErrMsg
GoTo ErrorHandler
ElseIf Application.WorksheetFunction.Index(XRange, 2, 1) < Application.WorksheetFunction.Index(XRange, 1, 1) And X < X1 Then
ErrMsg = "Data Out of Range " & ErrMsg
GoTo ErrorHandler
End If
Else
If Application.WorksheetFunction.Index(XRange, 1, 2) > Application.WorksheetFunction.Index(XRange, 1, 1) Then
X0Pos = Application.WorksheetFunction.Match(X, XRange, 1)
Else
X0Pos = Application.WorksheetFunction.Match(X, XRange, -1)
End If
If XRange.Count = X0Pos Then
XFlag = True
X1Pos = X0Pos
Else
X1Pos = 1 + X0Pos
End If
X0 = Application.WorksheetFunction.Index(XRange, 1, X0Pos)
FX0 = Application.WorksheetFunction.Index(ValueRange, 1, X0Pos)
X1 = Application.WorksheetFunction.Index(XRange, 1, X1Pos)
FX1 = Application.WorksheetFunction.Index(ValueRange, 1, X1Pos)
If Application.WorksheetFunction.Index(XRange, 1, 2) > Application.WorksheetFunction.Index(XRange, 1, 1) And X > X1 Then
ErrMsg = "Data Out of Range " & ErrMsg
GoTo ErrorHandler
ElseIf Application.WorksheetFunction.Index(XRange, 1, 2) < Application.WorksheetFunction.Index(XRange, 1, 1) And X < X1 Then
ErrMsg = "Data Out of Range " & ErrMsg
GoTo ErrorHandler
End If
End If
'
' Transform to logarithmic interpolation if needed
'
If XLog Then
X0 = Log(X0) / Log(10)
X1 = Log(X1) / Log(10)
X = Log(X) / Log(10)
End If
'
' Calculate Normalized DeltaX
'
If XFlag Then
DeltaX = 0
Else
DeltaX = (X - X0) / (X1 - X0)
End If
'
LOOKUPX = FX0 + DeltaX * (FX1 - FX0) ' Calculate the interpolated result
'
Exit Function ' Exit to avoid handler.
'
' Display user defined or default error message on error.
'
ErrorHandler:
MsgBox ErrMsg, , "LOOKUPX Function Error"
Err.Clear ' Clear Err object fields
LOOKUPX = ""
End Function