Here is my interpretation of using Interpolation for Missing Buckets rolled up into an Excel VBA UDF. This UDF Interpolation Function provides Linear Interpolation of missing buckets with the ability to avoid inflation by rebalancing the values if required. It also allows the use of a Fixed Start value and a Fixed End value with two coefficients to adjust these values further, again, if required. Copy & Paste this Code into any Standard Code Module Back · Purchase
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | Public Function Interpolation(ByVal Known_ys As Range, Optional ByVal FixedStart As Boolean = False, Optional ByVal FixedEnd As Boolean = False, Optional ByVal StartCoefficient As Double = 1, Optional ByVal EndCoefficient As Double = 1, Optional Rebalance As Boolean = True) As Variant Dim Anchor As Boolean Dim Share As Double Dim TempShare As Double Dim SUM(1) Dim X As Long Dim Y As Long Dim Z As Long Dim FirstIndex As Long Dim NextIndex As Long Dim LastFirstIndex As Long Dim LastNextIndex As Long Dim V As Variant V = Known_ys FirstIndex = 1 NextIndex = 1 Anchor = False For X = 1 To UBound(V, 2) If V(1, X) <> Empty Then V(1, X) = Val(V(1, X)) If V(1, X) <= 0 Then V(1, X) = Empty End If Next X SUM(0) = Application.WorksheetFunction.SUM(V) For X = 1 To UBound(V, 2) If V(1, X) <= 0 Then If Not Anchor Then If NextIndex > FirstIndex Then FirstIndex = NextIndex NextIndex = X Anchor = True End If End If If V(1, X) > 0 Then Z = Z + 1 If Anchor Then NextIndex = X Anchor = False Else FirstIndex = X End If End If If V(1, X) > 0 And NextIndex > FirstIndex Then Anchor = False If V(1, NextIndex) > V(1, FirstIndex) Then If V(1, FirstIndex) <= 0 Then Share = (V(1, NextIndex) - V(1, FirstIndex)) / ((NextIndex - FirstIndex) + 1) Else Share = (V(1, NextIndex) - V(1, FirstIndex)) / ((NextIndex - FirstIndex)) End If Else Share = (V(1, FirstIndex) - V(1, NextIndex)) / ((NextIndex - FirstIndex)) End If TempShare = V(1, FirstIndex) If V(1, FirstIndex) <= 0 Then For Y = FirstIndex To NextIndex - 1 If FixedStart Then V(1, Y) = V(1, NextIndex) * StartCoefficient Else V(1, Y) = (V(1, Y) + TempShare + Share) * StartCoefficient TempShare = TempShare + Share 'V(1, Y) End If Next Y ElseIf V(1, NextIndex) > V(1, FirstIndex) Then For Y = FirstIndex + 1 To NextIndex - 1 V(1, Y) = (V(1, Y) + TempShare + Share) TempShare = TempShare + Share 'V(1, Y) Next Y Else TempShare = V(1, NextIndex) For Y = NextIndex - 1 To FirstIndex + 1 Step -1 V(1, Y) = (V(1, Y) + TempShare + Share) TempShare = TempShare + Share 'V(1, Y) Next Y End If Else TempShare = 0 NextIndex = X LastFirstIndex = FirstIndex LastNextIndex = NextIndex End If Next X If V(1, NextIndex) <= 0 Then Share = (V(1, FirstIndex) - V(1, NextIndex)) / ((NextIndex - FirstIndex + 1)) TempShare = 0 For Y = FirstIndex + 1 To NextIndex If FixedEnd Then TempShare = V(1, FirstIndex) * EndCoefficient If TempShare < 0 Then TempShare = 0 V(1, Y) = TempShare Else TempShare = (V(1, Y - 1) - Share) * EndCoefficient If TempShare < 0 Then TempShare = 0 V(1, Y) = TempShare End If Next Y End If SUM(1) = Application.WorksheetFunction.SUM(V) If Rebalance Then For X = 1 To UBound(V, 2) V(1, X) = V(1, X) / SUM(1) * SUM(0) Next X End If Interpolation = VEnd Function |
Public Function Interpolation(ByVal Known_ys As Range, Optional ByVal FixedStart As Boolean = False, Optional ByVal FixedEnd As Boolean = False, Optional ByVal StartCoefficient As Double = 1, Optional ByVal EndCoefficient As Double = 1, Optional Rebalance As Boolean = True) As Variant
Dim Anchor As Boolean
Dim Share As Double
Dim TempShare As Double
Dim SUM(1)
Dim X As Long
Dim Y As Long
Dim Z As Long
Dim FirstIndex As Long
Dim NextIndex As Long
Dim LastFirstIndex As Long
Dim LastNextIndex As Long
Dim V As Variant
V = Known_ys
FirstIndex = 1
NextIndex = 1
Anchor = False
For X = 1 To UBound(V, 2)
If V(1, X) <> Empty Then V(1, X) = Val(V(1, X))
If V(1, X) <= 0 Then
V(1, X) = Empty
End If
Next X
SUM(0) = Application.WorksheetFunction.SUM(V)
For X = 1 To UBound(V, 2)
If V(1, X) <= 0 Then
If Not Anchor Then
If NextIndex > FirstIndex Then FirstIndex = NextIndex
NextIndex = X
Anchor = True
End If
End If
If V(1, X) > 0 Then
Z = Z + 1
If Anchor Then
NextIndex = X
Anchor = False
Else
FirstIndex = X
End If
End If
If V(1, X) > 0 And NextIndex > FirstIndex Then
Anchor = False
If V(1, NextIndex) > V(1, FirstIndex) Then
If V(1, FirstIndex) <= 0 Then
Share = (V(1, NextIndex) - V(1, FirstIndex)) / ((NextIndex - FirstIndex) + 1)
Else
Share = (V(1, NextIndex) - V(1, FirstIndex)) / ((NextIndex - FirstIndex))
End If
Else
Share = (V(1, FirstIndex) - V(1, NextIndex)) / ((NextIndex - FirstIndex))
End If
TempShare = V(1, FirstIndex)
If V(1, FirstIndex) <= 0 Then
For Y = FirstIndex To NextIndex - 1
If FixedStart Then
V(1, Y) = V(1, NextIndex) * StartCoefficient
Else
V(1, Y) = (V(1, Y) + TempShare + Share) * StartCoefficient
TempShare = TempShare + Share 'V(1, Y)
End If
Next Y
ElseIf V(1, NextIndex) > V(1, FirstIndex) Then
For Y = FirstIndex + 1 To NextIndex - 1
V(1, Y) = (V(1, Y) + TempShare + Share)
TempShare = TempShare + Share 'V(1, Y)
Next Y
Else
TempShare = V(1, NextIndex)
For Y = NextIndex - 1 To FirstIndex + 1 Step -1
V(1, Y) = (V(1, Y) + TempShare + Share)
TempShare = TempShare + Share 'V(1, Y)
Next Y
End If
Else
TempShare = 0
NextIndex = X
LastFirstIndex = FirstIndex
LastNextIndex = NextIndex
End If
Next X
If V(1, NextIndex) <= 0 Then
Share = (V(1, FirstIndex) - V(1, NextIndex)) / ((NextIndex - FirstIndex + 1))
TempShare = 0
For Y = FirstIndex + 1 To NextIndex
If FixedEnd Then
TempShare = V(1, FirstIndex) * EndCoefficient
If TempShare < 0 Then TempShare = 0
V(1, Y) = TempShare
Else
TempShare = (V(1, Y - 1) - Share) * EndCoefficient
If TempShare < 0 Then TempShare = 0
V(1, Y) = TempShare
End If
Next Y
End If
SUM(1) = Application.WorksheetFunction.SUM(V)
If Rebalance Then
For X = 1 To UBound(V, 2)
V(1, X) = V(1, X) / SUM(1) * SUM(0)
Next X
End If
Interpolation = V
End Function
Function information is added to the Macro Table in the 'ThisWorkbook' Sheet giving you intellisense about the Named Arguments in the 'fx' (Formula Box) in Excel. Copy the Code below into the 'ThisWorkbook' Sheet Code Module:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 | Private Sub Workbook_Open() Dim FunctionName As String Dim FunctionDesc As String Dim ArgDesc(1 To 6) As String FunctionName = "Interpolation" FunctionDesc = "Performs Linear Interpolation on Known_ys with the ability to fix the Start & End values and rebalance any inflation" ArgDesc(1) = "Provide the Known_ys that will be used for Linear Interpolation" ArgDesc(2) = "Optional: Choose whether to use a Fixed Start value as opposed to Interpolation. True = yes, False = no, default = False" ArgDesc(3) = "Optional: Choose whether to use a Fixed End value as opposed to Interpolation. True = yes, False = no, default = False" ArgDesc(4) = "Optional: Start Coefficient used to multiply the Start value, default = 1" ArgDesc(5) = "Optional: End Coefficient used to multiply the End value, default = 1" ArgDesc(6) = "Optional: Rebalance used to evenly distribute the inflation due to Interpolation, default = True" Application.MacroOptions Macro:=FunctionName, Description:=FunctionDesc, Category:=vbNullString, ArgumentDescriptions:=ArgDescEnd Sub |
Private Sub Workbook_Open()
Dim FunctionName As String
Dim FunctionDesc As String
Dim ArgDesc(1 To 6) As String
FunctionName = "Interpolation"
FunctionDesc = "Performs Linear Interpolation on Known_ys with the ability to fix the Start & End values and rebalance any inflation"
ArgDesc(1) = "Provide the Known_ys that will be used for Linear Interpolation"
ArgDesc(2) = "Optional: Choose whether to use a Fixed Start value as opposed to Interpolation. True = yes, False = no, default = False"
ArgDesc(3) = "Optional: Choose whether to use a Fixed End value as opposed to Interpolation. True = yes, False = no, default = False"
ArgDesc(4) = "Optional: Start Coefficient used to multiply the Start value, default = 1"
ArgDesc(5) = "Optional: End Coefficient used to multiply the End value, default = 1"
ArgDesc(6) = "Optional: Rebalance used to evenly distribute the inflation due to Interpolation, default = True"
Application.MacroOptions Macro:=FunctionName, Description:=FunctionDesc, Category:=vbNullString, ArgumentDescriptions:=ArgDesc
End Sub
Use the UDF like this in any Worksheet in Excel for a range of any size (Example shown Range := $D28:$R28, 15 values):
1 2 3 4 5 | ' Interpolation (unbalanced)=Interpolation($D28:$R28,FALSE,FALSE,1,1,FALSE)' Interpolation (rebalanced)=Interpolation($D28:$R28) |
' Interpolation (unbalanced) =Interpolation($D28:$R28,FALSE,FALSE,1,1,FALSE) ' Interpolation (rebalanced) =Interpolation($D28:$R28)
Here are the Actuals values used for this demonstration detailing the Interpolation results for both unbalanced and rebalanced values. Please Note: zeros can be zero (0) or blank - the algorithm treats them as similar. Also negatives are removed by the algorithm and treated as zero / blank. I will underline the Interpolated values for the unbalanced series so that you can clearly see the values that have been Interpolated for the missing buckets. One last point is that for this algorithm we cannot start with a zero (0) hence we always divide by 'Gap' + 1 to ensure a non-zero start i.e. for 4 missing buckets and a first value of 8, we would Interpolate: 1.6, 3.2, 4.8, 6.4 and then 8, not: 0, 2, 4, 6, 8 or: 1, 2, 4, 6, 8
| Series | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Actuals | 0 | 0 | 4 | -1 | 8 | 11 | 3 | 6 | 9 | 7 | |||||
| Interpolation (unbalanced) | 1.3 | 2.7 | 4 | 5.3 | 6.7 | 8 | 11 | 3 | 4.5 | 6 | 7.5 | 9 | 7 | 4.7 | 2.3 |
| Interpolation (rebalanced) | 0.8 | 1.5 | 2.3 | 3.1 | 3.9 | 4.6 | 6.4 | 1.7 | 2.6 | 3.5 | 4.3 | 5.2 | 4.0 | 2.7 | 1.3 |
Chart demonstrating the VBA UDF Linear Interpolation Function on a range of 15 values, Fixed Start := False, Fixed End := False, Start Coefficient := 1, End Coefficient := 1, Rebalance := False. The Actuals series SUM to 48 and the Interpolation series SUM to 83 (unbalanced and with inflation)
Chart demonstrating the VBA UDF Linear Interpolation Function on a range of 15 values, Fixed Start := False, Fixed End := False, Start Coefficient := 1, End Coefficient := 1, Rebalance := True. The Actuals series and the Interpolation series both SUM to 48 (rebalanced without inflation)
Here is another Linear Interpolation using An Excel VBA UDF. This UDF provides Linear Interpolation of missing buckets by coearsing the first and last buckets to 1 if they are missing and/or they are negative or zero (0). This Interpolation routine uses a Slope and Intercept calculation to Interpolate between any Series of 'Known_ys' against any Series of 'Known_xs', meaning it can fit the Interpolation values for sequential or disparate periods, for example, given Known_ys of '2, 0 and 4' and 'Known_xs' periods of '7, 12 and 20' the period '12' of the 'Known_xs' for the value '0' will be interpolated to '2.77'. This Interpolation routine will inflate the final values as it does not rebalance the weightings of the values following Interpolation. Copy & Paste this Code into any Standard Code Module Back · Purchase
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | Public Function LinearInterpolate(ByVal Known_ys As Range, ByVal Known_xs As Range) As Variant Dim First As Long Dim Last As Long Dim X As Long Dim Y As Long Dim SizeOfYS As Long Dim Slope As Double Dim Intercept As Double Dim YS As Variant Dim XS As Variant YS = Known_ys SizeOfYS = UBound(YS, 2) XS = Known_xs For X = 1 To SizeOfYS If YS(1, X) <> Empty Then YS(1, X) = Val(YS(1, X)) If YS(1, X) <= 0 Then YS(1, X) = Empty End If If YS(1, 1) <= 0 Then YS(1, 1) = 1 If YS(1, SizeOfYS) <= 0 Then YS(1, SizeOfYS) = 1 Next X First = 0 For X = 1 To SizeOfYS If YS(1, X) <= 0 Then If First = 0 Then First = X - 1 ElseIf YS(1, X) > 0 And First > 0 Then Last = X For Y = First + 1 To X - 1 Slope = (YS(1, Last) - YS(1, First)) / (XS(1, Last) - XS(1, First)) Intercept = YS(1, First) - Slope * XS(1, First) YS(1, Y) = (Slope * XS(1, Y) + Intercept) Next Y First = 0 End If Next X LinearInterpolate = YSEnd Function |
Public Function LinearInterpolate(ByVal Known_ys As Range, ByVal Known_xs As Range) As Variant
Dim First As Long
Dim Last As Long
Dim X As Long
Dim Y As Long
Dim SizeOfYS As Long
Dim Slope As Double
Dim Intercept As Double
Dim YS As Variant
Dim XS As Variant
YS = Known_ys
SizeOfYS = UBound(YS, 2)
XS = Known_xs
For X = 1 To SizeOfYS
If YS(1, X) <> Empty Then YS(1, X) = Val(YS(1, X))
If YS(1, X) <= 0 Then
YS(1, X) = Empty
End If
If YS(1, 1) <= 0 Then YS(1, 1) = 1
If YS(1, SizeOfYS) <= 0 Then YS(1, SizeOfYS) = 1
Next X
First = 0
For X = 1 To SizeOfYS
If YS(1, X) <= 0 Then
If First = 0 Then First = X - 1
ElseIf YS(1, X) > 0 And First > 0 Then
Last = X
For Y = First + 1 To X - 1
Slope = (YS(1, Last) - YS(1, First)) / (XS(1, Last) - XS(1, First))
Intercept = YS(1, First) - Slope * XS(1, First)
YS(1, Y) = (Slope * XS(1, Y) + Intercept)
Next Y
First = 0
End If
Next X
LinearInterpolate = YS
End Function
Function information is added to the Macro Table in the 'ThisWorkbook' Sheet giving you intellisense about the Named Arguments in the 'fx' (Formula Box) in Excel. Copy the Code below into the 'ThisWorkbook' Sheet Code Module:
01 02 03 04 05 06 07 08 09 10 11 12 13 | Private Sub Workbook_Open() Dim FunctionName As String Dim FunctionDesc As String Dim ArgDesc(1 To 2) As String FunctionName = "LinearInterpolate" FunctionDesc = "Performs Linear Interpolation on Known_ys with the ability to Interpolate any period. Start and End are set to 1 if negative/zero/blank" ArgDesc(1) = "Provide the Known_ys that will be used for the Linear Interpolation, typically the Actuals" ArgDesc(2) = "Provide the Known_xs that will be used for Linear Interpolation, typically the Periods" Application.MacroOptions Macro:=FunctionName, Description:=FunctionDesc, Category:=vbNullString, ArgumentDescriptions:=ArgDescEnd Sub |
Private Sub Workbook_Open()
Dim FunctionName As String
Dim FunctionDesc As String
Dim ArgDesc(1 To 2) As String
FunctionName = "LinearInterpolate"
FunctionDesc = "Performs Linear Interpolation on Known_ys with the ability to Interpolate any period. Start and End are set to 1 if negative/zero/blank"
ArgDesc(1) = "Provide the Known_ys that will be used for the Linear Interpolation, typically the Actuals"
ArgDesc(2) = "Provide the Known_xs that will be used for Linear Interpolation, typically the Periods"
Application.MacroOptions Macro:=FunctionName, Description:=FunctionDesc, Category:=vbNullString, ArgumentDescriptions:=ArgDesc
End Sub
Use the UDF like this in any Worksheet in Excel for a range of any size:
1 2 | ' Known_ys = Actuals, '$D28:$S28' and Knowyn_xs = Periods (sequential), '$D27:$S27' =LinearInterpolate($D28:$S28,$D27:$S27) |
' Known_ys = Actuals, '$D28:$S28' and Knowyn_xs = Periods (sequential), '$D27:$S27' =LinearInterpolate($D28:$S28,$D27:$S27)
Here are the Actuals values used for this demonstration detailing the Interpolation results on Sequential Time Periods. I will underline the Interpolated values for the series so that you can clearly see the values that have been Interpolated for the missing buckets
| Series | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Actuals | 2 | 3 | 2 | 2 | 3 | 3 | 6 | 2 | 2 | 11 | 12 | |||||
| Interpolate | 2 | 2.5 | 3 | 2 | 2 | 2.5 | 3 | 3 | 4.5 | 6 | 2 | 2 | 5.0 | 8.0 | 11 | 12 |
Chart demonstrating the VBA UDF Linear Interpolate Function on a range of 16 sequential values
Here are the Actuals values used for this demonstration detailing the Interpolation results on Disparate Time Periods. I will underline the Interpolated values for the series so that you can clearly see the values that have been Interpolated for the missing buckets
| Series | 7 | 12 | 20 |
|---|---|---|---|
| Actuals | 2 | 4 | |
| Interpolate | 2 | 2.77 | 4 |
Chart demonstrating the VBA UDF Linear Interpolate Function on a range of 3 disparate values