Why does this function work in one sheet, but not another

GeeWhiz7

Board Regular
Joined
Nov 22, 2021
Messages
214
Office Version
  1. 365
Platform
  1. Windows
  2. MacOS
Little bit complicated code I found somewhere here on the forum, but cant seem to re-find.

That said, I want to use the very useful SMA function below (written by Bobby if I recall correctly?) and port it to work in the array calculations in vba, not in the sheet.
My first hiccup is that it works in a new worksheet, see second mini-sheet, but not in another sheet I have (first mini-sheet).

Goal: 1) Make work in any workbook and 2) only in vba array/memory by passing a array to it using a For Loop

Cell Formulas
RangeFormula
A2:A51A2=RANDBETWEEN(2,100)
B2:B51B2=SMA(A2:A51,10)
Press CTRL+SHIFT+ENTER to enter array formulas.


Book3
AB
1Input ArraySMA 5
288
37441
49258
57361.75
66662.6
72465.8
8351.6
91135.4
101323.4
113517.2
127627.6
136439.8
144145.8
156456
16249.4
177449
184445
193944.6
205542.8
218158.6
228260.2
236063.4
241057.6
256459.4
268961
276156.8
282650
295358.6
305857.4
314047.6
324644.6
335650.6
347354.6
359061
364762.4
377468
387070.8
391859.8
408057.8
415860
422049.2
437850.8
446059.2
452548.2
462541.6
479456.4
487656
498961.8
504966.6
512165.8
Sheet1
Cell Formulas
RangeFormula
B2:B51B2=SMA(A2:A51,5)
Press CTRL+SHIFT+ENTER to enter array formulas.


Code
VBA Code:
Function SMA(DataValues As Range, NumPeriods As Long, Optional ReturnElement As Long)
    Dim arrData, _
        arrSMA, _
        arrCumulative, _
        i As Long, _
        j As Long, _
        tempsum As Double
    
    NumPeriods = Abs(NumPeriods)
    
    arrData = Range_to_1D_Array(DataValues)
    arrData = ResizeArrayToAllNumeric(arrData, True)
    
    ReDim arrCumulative(1 To UBound(arrData)) As Double
    ReDim arrSMA(1 To UBound(arrData)) As Double
    
    For i = LBound(arrData) To UBound(arrData)
        tempsum = 0
        If i = 1 Then
            arrCumulative(i) = arrData(i)
        Else
            arrCumulative(i) = arrData(i) + arrCumulative(i - 1)
        End If
        If i < NumPeriods Then
            arrSMA(i) = arrCumulative(i) / i
        Else
            For j = i - NumPeriods + 1 To i
                tempsum = tempsum + arrData(j)
            Next j
            arrSMA(i) = tempsum / NumPeriods
        End If
    Next i
    
    If ReturnElement Then
        If ReturnElement > UBound(arrSMA) Then
            SMA = CVErr(xlErrNA)
        Else
            SMA = arrSMA(ReturnElement)
        End If
    Else
        If Application.Caller.Rows.Count > 1 Then
            SMA = Excel.Application.Transpose(arrSMA)
        Else
            SMA = arrSMA
        End If
    End If
    End Function


Function Range_to_1D_Array(ByVal Rng As Range)

    Dim ReturnArray, _
        arrTemp, _
        i As Long, _
        j As Long, _
        k As Long
    
    If Rng.Cells.Count = 1 Then
        ReDim ReturnArray(1 To 1)
        ReturnArray(1) = Rng
    Else
        If Rng.Columns.Count > 1 And Rng.Rows.Count > 1 Then
            arrTemp = Rng.Value
            ReDim ReturnArray(1 To UBound(arrTemp, 1) * UBound(arrTemp, 2))
            k = 0
            For i = 1 To UBound(arrTemp, 1)
                For j = 1 To UBound(arrTemp, 2)
                    k = k + 1
                    ReturnArray(k) = arrTemp(i, j)
                Next j
            Next i
            Erase arrTemp
        Else
            With Excel.Application
                ReturnArray = .Transpose(Rng)
                If Rng.Rows.Count = 1 Then ReturnArray = .Transpose(ReturnArray)
            End With
        End If
    End If
    
    Range_to_1D_Array = ReturnArray
    Erase ReturnArray
    End Function

Function ResizeArrayToAllNumeric(vArr, Optional ZeroMissingandText As Boolean = False)
    Dim vOut, _
        i As Long, _
        Counter As Long
        
    ReDim vOut(LBound(vArr) To UBound(vArr)) As Double
        For i = LBound(vArr) To UBound(vArr)
            If ZeroMissingandText Then
                Counter = Counter + 1
                If IsNumeric(vArr(i)) Then
                    vOut(i) = vArr(i)
                Else
                    vOut(i) = 0
                End If
            Else
                If IsNumeric(vArr(i)) Then
                    Counter = Counter + 1
                    vOut(Counter) = vArr(i)
                End If
            End If
        Next i
    ReDim Preserve vOut(1 To Counter) As Double
    ResizeArrayToAllNumeric = vOut
    Erase vOut
    End Function
Function ArrayDimensions(InputArray As Variant) As Long
    Dim n As Long

    If Not IsArray(InputArray) Or IsObject(InputArray) Then
        n = 0
        Exit Function
    Else
        n = 1
    End If

    On Error Resume Next
        Do
            n = n + 1
        Loop While (LBound(InputArray, n) <= UBound(InputArray, n))
        ArrayDimensions = n - 1
    Err.Clear
    On Error GoTo 0
    End Function
 

Excel Facts

What did Pito Salas invent?
Pito Salas, working for Lotus, popularized what would become to be pivot tables. It was released as Lotus Improv in 1989.

Forum statistics

Threads
1,223,885
Messages
6,175,187
Members
452,616
Latest member
intern444

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top