【问题标题】:Root Mean Square (rms) function in VBA?VBA中的均方根(rms)函数?
【发布时间】:2013-08-13 15:14:07
【问题描述】:

所以我在我的工作表中计算基本统计数据,它包含以下代码:

xxx = Application.worksheetfunction.平均(等等等等

yyy = Application.worksheetfunction.min(等等等等等等

zzz = Application.worksheetfunction.ma​​x(等等等等等等

我的问题:是否有一个 RMS 等效函数,我可以简单地将其插入该代码中具有“平均、最小值、最大值”函数的位置?如果没有,那么编写代码以找到 RMS 解决方案的最有效方法是什么?

我希望我已经足够清楚地说明了目标。我很好奇 VBA 是否有预定义的 RMS 函数,或者我是否必须创建某种用户定义的函数? ~ 我也很陌生,所以如果没有简单的代码行来写,我将不得不在 UDF 上做更多的阅读。

编辑:

我有大约 30,000 行,为简单起见:假设有两列。 A 列有年份,即 1941 年或 2008 年之前的任何时间。B 列是一个数值。我只是想把代码放在一起,给出平均值、最小值、最大值和 RMS 值的十年摘要。

【问题讨论】:

  • 您能解释一下我的“最小值”和“最大值”与 RMS 的关系吗?
  • 此信息很有帮助,但我正在循环通过多个不同年份的几十年。我没有手动滚动并定义范围,而是在 VBA 中将其自动化;它允许我在 VBA 中使用“SumSq”和“CountA”函数。然而,VBE 推荐的唯一选项是“SqrtPi”函数,而不是简单的“Sqrt”。我肯定缺乏这方面的知识,但如果你能在“sqrt”的正确方向上稍微推动我一点,那将是最有帮助的!
  • 当然,我有大约 30,000 行,为简单起见:想象两列。 A 列有年份,即 1941 年或 2008 年之前的任何时间。B 列是一个数值。我只是想把代码放在一起,给出平均值、最小值、最大值和 RMS 值的十年摘要。
  • 好的,但我还是不明白。您从未在原始问题中声明您想要单独的 RMS 值。因此,在我的电气世界中,我只需乘以 SQRT(2) 即可得到 RMS 值,然后取平均值并确定最小值和最大值,但我认为你想要一些不同的东西。
  • @pnuts ,是的,在这种较小的情况下,数据透视表可以很好地工作;然而,这只是我正在进行的整个项目的一小部分。我只是错过了要添加到这个块中的正确 VBA 语法。不过我很感激这个小费!

标签: excel vba worksheet-function


【解决方案1】:

你可以做平均

=SQRT(SUMSQ(A:A)/COUNTA(range))

或在 VBA 中:

r = (Application.WorksheetFunction.SumSq(Range("A:A")) / Range("A:A").Count) ^ (1 / 2)

【讨论】:

  • 此信息很有帮助,但我正在循环通过多个不同年份的几十年。我没有手动滚动并定义范围,而是在 VBA 中将其自动化;它允许我在 VBA 中使用“SumSq”和“CountA”函数。然而,VBE 推荐的唯一选项是“SqrtPi”函数,而不是简单的“Sqrt”。我肯定缺乏这方面的知识,但如果你能在“sqrt”的正确方向上稍微推动我一点,那将是最有帮助的!
  • @WATERflowTech,好的,我还添加了一个 VBA 函数,您可能想要使用命名范围。
  • 就是这样,很好的调用 n 次方。我没有想到这一点,但毫无疑问,将来会记住这一点!谢谢兰斯!
【解决方案2】:

一个 VBA 函数,它接受数组(任何等级)和具有多个区域的范围(不连续的范围,如 A4:B6、C11:D15),甚至是公式中的范围的联合。它会跳过非数字数据类型(包括日期、布尔值、空格等)。

您可以在 VBA 代码中使用它,或在工作表公式中用作 UDF,例如:

"=RMS(A1:A10)"(基本用法)

"=RMS(A1:A10,C1:C10)"(多个范围(或相关的数组))

"{=RMS({1,2,3,4})}"(使用 Ctrl+shift+enter 输入的数组公式)

Function RMS(ParamArray args()) As Double

    Dim arg, arr, area As Range, ss As Double, n As Long

    For Each arg In args
        If TypeOf arg Is Range Then
            For Each area In arg.Areas
                arr = area.value
                If VarType(arr) < vbArray Then
                    queryRmsElements Array(arr), ss, n
                Else
                    queryRmsElements arr, ss, n
                End If
            Next area
        ElseIf VarType(arg) > vbArray Then
            queryRmsElements arg, ss, n
        Else
            Err.Raise 1, "RMS", "Invalid Argument"
        End If
    Next arg

    RMS = (ss / n) ^ 0.5

End Function
Private Sub queryRmsElements(ByRef elements, ByRef ss As Double, ByRef n As Long)
    Static element As Variant
    'Enumerate to cover rank > 1 (vs. Iterate)
    For Each element In elements
        Select Case VarType(element)
            Case VbVarType.vbByte, _
                 VbVarType.vbCurrency, _
                 VbVarType.vbDecimal, _
                 VbVarType.vbDouble, _
                 VbVarType.vbInteger, _
                 VbVarType.vbLong, _
                 VbVarType.vbSingle
                 ss = element ^ 2 + ss
                 n = n + 1
            Case Else
        End Select
    Next element
End Sub

【讨论】:

    【解决方案3】:

    这个对我有用:

    Function RMS(Intervalo As Range)
    
    Dim SomaQ As Double
    Dim Tamanho As Integer
    
    SomaQ = 0
    Tamanho = Intervalo.Count
    SomaQ = Application.WorksheetFunction.SumSq(Intervalo)
    RMS = Sqr(SomaQ / Tamanho)
    
    End Function
    

    【讨论】:

      猜你喜欢
      • 2012-01-04
      • 2012-07-28
      • 2017-04-19
      • 1970-01-01
      • 1970-01-01
      • 2021-04-04
      • 1970-01-01
      • 2017-10-13
      • 2012-10-21
      相关资源
      最近更新 更多