【问题标题】:Creating a function in excel VBA to calculate the average point in a circular set of numbers在excel VBA中创建一个函数来计算一组圆形数字中的平均点
【发布时间】:2020-08-04 14:26:03
【问题描述】:

在这方面仍然相当业余,所以请保持温和。我正在尝试创建一个给出一组数字平均值的函数。这组数字实际上是一个齿轮的齿。乳牙始终是 1 号牙齿(可识别为涂漆),在顺时针旋转的牙齿上记录损坏或停止,因此牙齿 7 和 23 处的损坏将在距起始牙齿的 7 和 23 齿处。现在,当您计算正常平均值时会出现异常,因为根据标准平均值,第 3、4 和 33 颗牙齿的停顿平均值实际上是 1 而不是 14.33。我已经计算出找到平均值,平均而言,我的意思是更接近一组圆形数字的中位数。我在范围内的每个值上加一,并使用 MOD 函数计算最大和最小数字之间的差。一旦我确定了最短差值的第一个位置,这只是从新平均值中减去增量值的情况。它可能在表格中更好地描述......

如您所见,真正的平均值或中位数是牙齿 1,即平均值减去第一个具有最小差异的数字组的增量。 我目前要进行这些计算的代码给出了 value# 错误,但我对自定义函数的经验非常少,我不知道从哪里开始纠正问题,将不胜感激指针,解决方案将太棒了。非常感谢。

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

【问题讨论】:

  • cell.Value = 37... 如果您将其作为单元格中的用户定义函数调用,则无法修改单元格的值。
  • 只要rng由多个单元格组成,rng.Value就是一个二维数组。 Here's 更多关于数组和范围的阅读。
  • 感谢 BigBen,这看起来是一个很棒的资源,它看起来很好解释。我将不得不离开并通过一些实验来阅读它几次以完全理解,因为我是一个“玩几次”类型的学习者。谢谢。
  • BigBen,我浏览了您链接的资源,它解释数组主题的方式非常简单,一定是因为我理解它!我现在修改了我的代码以将值放入数组并执行计算,但我认为结果是错误的,我的结果是 4,例如它应该是 1。我认为问题是我正在添加下一个递增到已经递增的数组值,但我不确定我将如何编码只想使用初始值。除了编写代码的次数与我咬牙切齿的次数相同之外。救命!
  • 尤里卡!我得到了解决方案 BigBen !!!我只需要在 i 的每次迭代开始时将范围添加回数组。本质上,每次都对其进行格式化,以准备执行新的计算。感谢您指导使用阵列和资源。 :-)

标签: excel vba average custom-function


【解决方案1】:

感谢 BigBen 指导使用数组。为了计算一组循环数字的平均值,我使用了下面的代码。我希望这个例子可以帮助其他有类似问题的人。如果您需要不同数量的齿轮齿,您只需适当更改 MOD 值即可。

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

【讨论】:

    【解决方案2】:

    这个怎么样?似乎返回与您的示例相同的值,但如果有更多的样本计算来测试会很有用...

    Function AvgDistance(vals As Range, teeth) As Double
        Dim arr, i As Long, tot As Long, v
        arr = vals.Value
        tot = 0
        For i = 1 To UBound(arr, 1)
            v = arr(i, 1)
            tot = tot + IIf(v > (teeth / 2), v - teeth, v)
        Next i
        AvgDistance = tot / UBound(arr, 1)
    End Function
    

    【讨论】:

    • 感谢蒂姆花时间,但第一个答案已交付。我确实尝试了这个功能,但它的答案与我的不同。不过再次感谢你。 :-)
    猜你喜欢
    • 2019-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-07
    • 2021-11-22
    相关资源
    最近更新 更多