FOR Excel中的UDF内部循环不起作用

时间:2018-12-27 23:07:18

标签: excel vba

我当前正在编程一个Excel函数,该函数应该返回数组最后5个非空位置的平均值。为此,我想在函数内部遍历数组,如下所示:

<hash>:"2.0"

问题:在到达第一个Function AVERAGE_LAST_5(rng As Range) As Long Dim x As Integer, i As Integer, j As Integer, sum As Integer Dim myArr() As Variant myArr() = Application.Transpose(Application.Transpose(rng)) x = rng.Count i = 0:: j = 0:: sum = 0 For i = x To 1 Step -1 If myArr(x).Value <> 0 Then sum = sum + myArr(x) j = j + 1 Else End If If j = 5 Then Stop x = x - 1 Next AVERAGE_LAST_5 = sum / 5 End Function 时,for循环不起作用。

有人有同样的问题吗? 有人可以帮我吗?

3 个答案:

答案 0 :(得分:0)

myarr将是一个二维数组,而不是一个范围。您需要提供两个尺寸:

remove()

答案 1 :(得分:0)

阵列更快

最终版本(希望如此)

此版本还具有NumberOfLastValues参数(必填),因此您可以选择将要累加多少个值,并使用GoSub...Return语句将其缩短,因为{ {1}}语句按行和按列相同。
有关其他详细信息,请参见下面的“第一版”。

用法

在VBA中

If

在Excel中

Sub LastAverage()
  Debug.Print AvgLast(Range("B4:G14"), 5)
End Sub

=AvgLast(B4:G14,5)

第一版

如果至少有1个值且最多有5个值,则将返回平均值,否则将返回0。

Row_0_Column_1 arguments参数默认情况下为0,表示搜索是按行完成的(第一个循环)。如果为1,则按列(第二循环)进行搜索。

最基本的是将范围粘贴(分散)到数组中,然后在数组中搜索现有的“数字”值,而不是总和的“”值,并且在达到第五个值时会“跳”出循环并将总和除以5。


Function AvgLast(SearchRange As Range, ByVal NumberOfLastValues As Long, _
    Optional ByVal Row_0_Column_1 As Integer = 0) As Double

  Dim vntRange As Variant   ' Range Array

  Dim i As Long             ' Range Array Rows Counter
  Dim j As Integer          ' Range Array Columns Counter
  Dim k As Long             ' Values Counter
  Dim dblSum As Double      ' Values Accumulator

  If SearchRange Is Nothing Then Exit Function

  vntRange = SearchRange.Value

  If Row_0_Column_1 = 0 Then
    ' By Row
    For i = UBound(vntRange) To 1 Step -1
      For j = UBound(vntRange, 2) To 1 Step -1
        GoSub Calc
      Next
    Next
   Else
    ' By Column
    For j = UBound(vntRange, 2) To 1 Step -1
      For i = UBound(vntRange) To 1 Step -1
        GoSub Calc
      Next
    Next
  End If

TiDa:
  If k > 0 Then
    AvgLast = dblSum / k
  End If
Exit Function

Calc:
  If vntRange(i, j) <> "" And IsNumeric(vntRange(i, j)) Then
    k = k + 1
    dblSum = dblSum + vntRange(i, j)
    If k = NumberOfLastValues Then GoTo TiDa
  End If
Return

End Function

答案 2 :(得分:0)

经过几天的辛苦工作后,我终于有一些时间来改进我的功能,充分利用您的技巧。

我进行了一些更改,以使该函数可以处理1行或1列范围。还添加了基本错误处理,并且还提供了一个功能discripton(在FX Excel按钮下)。

随时评论和/或使用代码。 结果如下:

Function AVERAGE_LAST_N(rng As Range, N As Integer)

Dim NrN As Integer, NrR As Integer, NrC As Integer
Dim i As Integer, j As Integer
Dim sum As Double
Dim myArr As Variant

    NrN = rng.Count           'Number of array positions
    NrR = rng.Rows.Count      'Number of Rows in the array
    NrC = rng.Columns.Count   'Number of Rows in the array
    i = 0:: j = 0:: sum = 0   'Counters

    '####################################################'
    '## Transpose Range into array if row or if column ##'
    '####################################################'

          If rng.Rows.Count > 1 And rng.Columns.Count = 1 Then             'Transpose a Column Range into an Array
               myArr = Application.Transpose(rng)

          ElseIf rng.Rows.Count = 1 And rng.Columns.Count > 1 Then         'Transpose a Row Range into an Array
              myArr = Application.Transpose(Application.Transpose(rng))

          ElseIf rng.Rows.Count > 1 And rng.Columns.Count > 1 Then         'Retunrs an Error if Range is a Matrix *ERR_002*
              AVERAGE_LAST_N = "ERR_002"
              Exit Function

          End If

    '####################################################'
    '## Transpose Range into array if row or if column ##'
    '####################################################'


    '################'
    '## Start Main ##'
    '################'

          For i = NrN To 1 Step -1
               If IsNumeric(myArr(NrN)) Then
                    sum = sum + myArr(NrN)
                    j = j + 1

               End If

               If j = N Then Exit For

               NrN = NrN - 1

          Next

          AVERAGE_LAST_N = sum / N

    '##############'
    '## End Main ##'
    '##############'


    '####################'
    '## Error Debuging ##'
    '####################'

          If j < N Then
              AVERAGE_LAST_N = "ERR_001"
              Exit Function
          End If

    '####################'
    '## Error Debuging ##'
    '####################'

End Function

Sub DescribeFunction()

   Dim FuncName As String
   Dim FuncDesc As String
   Dim Category As String
   Dim ArgDesc(1) As String

   FuncName = "AVERAGE_LAST_N"
   FuncDesc = "Returns the average of the last N non-empty values in the selected Range"
   Category = 14 'Text category
   ArgDesc(0) = "Range that contains the values" & Chr(10) & _
               "ERR_001 - There are not enought non-empty or null values in the range" & Chr(10) & _
               "ERR_002 - Selected range is a matrix and not a row or column range"

   ArgDesc(1) = "Dimention of the sample" & Chr(10) & _
               "ERR_001 - There are not enought non-empty or null values in the range" & Chr(10) & _
               "ERR_002 - Selected range is a matrix and not a row or column range"

   Application.MacroOptions _
       Macro:=FuncName, _
       Description:=FuncDesc, _
       Category:=Category, _
       ArgumentDescriptions:=ArgDesc

End Sub


'#######################################################################################

'                   ###############################################
'                   #############      Error DB      ##############
'                   ###############################################
'
'
'    ERR_001 - There are not enought non-empty values in the range
'    ERR_002 - Selected range is a matrix and not a row or column range
'

拉法