excelvbaaveragecustom-function

Function in Excel VBA to calculate the average point in a circular set of numbers


I am trying to create a function that gives the average of a set of numbers.

The numbers are the tooth positions of a cog with 37 teeth. The primary tooth is tooth 1 (identifiable as painted). Damage or stoppage is recorded on teeth in a clockwise rotation so damage at teeth 7 and 23 would be at 7 and 23 teeth from the starting tooth.

An anomaly occurs when calculating an average. The average of stoppages at teeth 3, 4 and 33 would be 1 not 14.33 as per a standard average.

To calculate the average, and by average I mean nearer the median of a set of circular numbers. I add one to each value in the range and calculate the difference between the maximum and minimum numbers using the MOD function. Once I identify the first position of the shortest difference it is a case of subtracting the incremented value from the new average.

Described in a table.
enter image description here

The real average or median is tooth 1, which is the average minus the increment of the first number set with the smallest difference.

The code is giving a value# error.

Public Function AVGDISTCALC(rng As Range)
'Determines the average distance of a number of distances on a 37 tooth wheel.
Dim x As Integer
Dim i As Integer
Dim avg As Integer
Dim diff As Integer
Dim Arr() As Variant
Dim r As Long
Dim c As Long
Application.ScreenUpdating = False

    'Write the range to an array.
    Arr = rng
    'Cycle through each increment on the 37 tooth wheel.
    diff = 38
    For i = 1 To 37
        Arr = rng
        'For each increment calculate the min and max of the range.
        For r = 1 To UBound(Arr, 1)
            For c = 1 To UBound(Arr, 2)
                If (Arr(r, c) + i) Mod 37 = 0 Then
                    Arr(r, c) = 37
                Else
                    Arr(r, c) = (Arr(r, c) + i) Mod 37
                End If
            Next c
        Next r
        If WorksheetFunction.Max(Arr) - WorksheetFunction.Min(Arr) < diff Then
            diff = WorksheetFunction.Max(Arr) - WorksheetFunction.Min(Arr)
            avg = WorksheetFunction.Average(Arr)
            x = i
        End If
    Next i
    
    AVGDISTCALC = avg - x
    
End Function

Solution

  • Thanks to BigBen for the steer onto using an array. To calculate the average of a circular set of numbers I used the code below. I hope this example helps anyone else with similar issues. If you need a different number of cog teeth you should just change the MOD value appropriately.

    Public Function AVGDISTCALC(rng As Range)
    'Determines the average distance of a number of distances on a 37 tooth wheel.
    Dim x As Integer
    Dim i As Integer
    Dim avg As Integer
    Dim diff As Integer
    Dim Arr() As Variant
    Dim r As Long
    Dim c As Long
    Application.ScreenUpdating = False
    
        'Write the range to an array.
        Arr = rng
        'Cycle through each increment on the 37 tooth wheel.
        diff = 38
        For i = 1 To 37
        Arr = rng
            'For each increment calculate the min and max of the range.
            For r = 1 To UBound(Arr, 1)
                For c = 1 To UBound(Arr, 2)
                    If (Arr(r, c) + i) Mod 37 = 0 Then
                        Arr(r, c) = 37
                    Else
                        Arr(r, c) = (Arr(r, c) + i) Mod 37
                    End If
                Next c
            Next r
            If WorksheetFunction.Max(Arr) - WorksheetFunction.Min(Arr) < diff Then
                diff = WorksheetFunction.Max(Arr) - WorksheetFunction.Min(Arr)
                avg = WorksheetFunction.Average(Arr)
                x = i
            End If
        Next i
        
        Select Case avg - x
        Case 0
            AVGDISTCALC = 37
        Case Is > 0
            AVGDISTCALC = avg - x
        Case Is < 0
            AVGDISTCALC = (avg - x) + 37
        End Select
        
    End Function