2012-09-12 276 views
2

我有一個函數,它將一系列值作爲輸入(只是一列)以及一些閾值。我想返回一個範圍,該範圍經過濾以包含來自原始範圍的所有大於閾值的值。我有以下代碼:Excel UDF濾波器範圍

Public Function FilterGreaterThan(Rng As Range, Limit As Double) As Range 

Dim Cell As Range 
Dim ResultRange As Range 

For Each Cell In Rng 
    If Abs(Cell.Value) >= Limit Then 
     If ResultRange Is Nothing Then 
      Set ResultRange = Cell 
     Else 
      Set ResultRange = Union(ResultRange, Cell) 
     End If 
    End If  
Next 
Set FilterGreaterThan = ResultRange 
End Function 

的問題是,一旦數量低於閾值,即一個後其他數字,均高於閾值不被添加到的範圍內。

例如:

Threshold - 2 

Numbers - 

3 
4 
1 
5 

它將循環通過添加3和4,但5不會被添加。我最終得到#value錯誤。但我沒有錯誤,它工作正常,如果我只輸入範圍-3,4或範圍-3,4,1。

+0

嗨之後,你如果將函數放入另一個函數(如= SUM(FilterGreaterThan(A1:A7,2))中,則函數可以正常工作。我認爲你遇到的問題是,你將= FilterGreaterThan(A1:A7,2)放在一個單元格中,當它返回一個多區域範圍時,你會得到一個#VALUE!錯誤。即使如此,我還是不明白從FilterGreaterThan(A1:A7,2)返回的結果,因爲你只是從範圍內取回(似乎是)隨機數。 –

+0

如果在End Function之前添加「Debug.Print FilterGreaterThan.Address」,您可以看到函數的範圍地址。它看起來像UDF可能不喜歡不連續的範圍。 – user3357963

回答

2

它看起來像UDF不喜歡非連續範圍被寫回數組。

解決方法之一是重新編寫UDF,如下所示。它假定輸出數組只在列中,但允許多列輸入。

Option Explicit 

Public Function FilterGreaterThan(Rng As Range, Limit As Double) As Variant 

Dim Cell As Range 
Dim WriteArray() As Variant 
Dim i As Long 
Dim cellVal As Variant 
Dim CountLimit As Long 

CountLimit = WorksheetFunction.CountIf(Rng, ">=" & Limit) 
ReDim WriteArray(1 To CountLimit, 1 To 1) 'change if more than 1 column 
For Each Cell In Rng 

    cellVal = Cell.Value 
    If Abs(cellVal) >= Limit Then 
      i = i + 1 'change if more than 1 column 
      WriteArray(i, 1) = cellVal 'change if more than 1 column 
    End If 
Next 
FilterGreaterThan = WriteArray 
End Function 
+0

+1雖然如果'CountLimit'爲0,那麼如果調用UDF,它將返回'#VALUE!'(而不是'#N/A')。如果從VBA調用,那麼如果'CountLimit'爲0,則會得到「下標超出範圍」錯誤 – barrowc

+0

您的權利,沒有錯誤處理並且假定CountLimit> 0。 – user3357963

+0

我只看了一下代碼。 CountLimit = WorksheetFunction.CountIf(Rng,「> =」&Limit)似乎沒有考慮絕對值考慮因素。不知道在哪裏添加,雖然 – user1666842

2

OOO最先到達那裏,但我打字出來,所以我現在不妨將它張貼。該版本將作爲正確大小的列向量返回。

如果沒有匹配,則在一個1由1陣列返回#N/A(這是當沒有足夠的值來填充所述陣列的陣列功能的正常行爲一致)

EDIT2:更新功能感謝意見從OOO

Public Function FilterGreaterThan(Rng As Range, Limit As Double) As Variant() 

Dim inputCell As Range ' each cell we read from 
Dim resultCount As Integer ' number of matching cells found 
Dim resultValue() As Variant ' array of cell values 

resultCount = 0 
ReDim resultValue(1 To 1, 1 To Rng.Cells.Count) 

For Each inputCell In Rng 
    If Abs(inputCell.Value) >= Limit Then 
     resultCount = resultCount + 1 
     resultValue(1, resultCount) = inputCell.Value 
    End If 
Next inputCell 

' Output array must be two-dimensional and we can only 
' ReDim Preserve the last dimension 
If (resultCount > 0) Then 
    ReDim Preserve resultValue(1 To 1, 1 To resultCount) 
Else 
    resultValue(1, 1) = CVErr(xlErrNA) 
    ReDim Preserve resultValue(1 To 1, 1 To 1) 
End If 

' Transpose the results to produce a column rather than a row 
resultValue = Application.WorksheetFunction.Transpose(resultValue) 

FilterGreaterThan = resultValue 

End Function 

編輯:工程確定爲我測試值在下面的評論:

Excel file showing FilterGreaterThan UDF working correctly

我敢肯定你知道這一點,但不包括{}字符輸入數組公式時 - Excel將他們你按下Ctrl-Shift鍵輸入

+0

謝謝!不幸的是,我繼續在你的代碼中出現#value錯誤。有什麼想法嗎?示例我正在使用: 要過濾的Rng值:-0.003742158,0.004134996,-0.002937923 限制:0.0008 – user1666842

+0

您的答案是正確的。我做的唯一的改變是在開始時Dim數組爲全尺寸,'ReDim保留resultValue(1到1,1到resultCount)'只在轉置前一次結束 - 最大數組大小爲'rng .cells.count'。此外,我們都把結果值作爲一個值而不是數組,如果只有一個單元格:) – user3357963

+0

@ooo謝謝 - 我已經更新了我的答案,以納入這些建議 – barrowc