2016-02-15 9 views
1

此函數用於計算閉合遍歷的面積。當作爲一個子書寫並分配給特定的單元格時,該子作品完美無缺。但是,當作爲函數使用時(如下所示),它只返回零。爲什麼? 「功能設計,以適應任何數量的橫向兩側Excel中的UDF VBA編輯器僅在需要Double時返回零點

Public Function TraverseArea() As Double 
Dim Area As Double 
Area = 0 
Range("N2").Select 
Area = (ActiveCell.Value * (Range("M2").End(xlDown).Offset(-1, 0).Value - ActiveCell.Offset(1, -1).Value)) 
ActiveCell.Offset(1, 0).Select 

While ActiveCell.Offset(1, -1) <> "" 
    Area = Area + (ActiveCell.Value * (ActiveCell.Offset(-1, -1).Value - ActiveCell.Offset(1, -1).Value)) 
    ActiveCell.Offset(1, 0).Select 
Wend 
If Area < 0 Then 
    Area = Area * -1 
End If 
Area = Area/2 
TraverseArea = Area 
End Function 
+0

爲什麼選擇單元格並在函數中使用activecell?從我所看到的您不需要選擇這些單元格,您可以在不選擇它的情況下閱讀單元格內容。 –

+0

我使用activecell的方式是從上到下逐步瀏覽Northings和Eastings列表直到結束(可以是任意數量的單元格)。你絕對沒有必要選擇每個單元格,但是,這仍然不能解釋爲什麼函數只返回零而不是計算區域。 – Jon

+1

停下來,逐行逐行(VBE中的F8),並在代碼運行時留意AREA。我建議在調用函數時移除activecell並傳入單元格引用。如果你選擇在運行時傳入活動單元,那就這樣吧,但它比將函數鎖定到單元引用好得多。此外,我會將While循環更改爲next,循環範圍而不是查找空白,這樣您可以引用範圍而不需要偏移。 –

回答

2

我沒有你的數據或片狀結構的,所以這是所有我的頭,但是這應該給你的,你怎麼能有你的功能的想法沒有特別使用硬編碼範圍。

Sub TestFunction() 
    MsgBox TraverseArea(Range("N2"), Range("M2").End(xlDown).Offset(-1, -1)) 
End Sub 

Public Function TraverseArea(MyRange As Range, MySecondRange As Range) As Double 
Dim Area As Double, lr As Long, X as long 
lr = Cells(Rows.Count, MyRange.Column).End(xlUp).Row 
Area = (MyRange.Value * (MySecondRange.Value - MyRange.Offset(1, -1).Value)) 
For X = MyRange.Row To lr 
    If Cells(X, MyRange.Column - 1) = "" Then Exit For 
    Area = Area + (ActiveCell.Value * (ActiveCell.Offset(-1, -1).Value - ActiveCell.Offset(1, -1).Value)) 
Next 
If Area < 0 Then Area = Area * -1 
Area = Area/2 
TraverseArea = Area 
End Function 

這很可能會需要一些調試,但應該足以給你什麼,我想在我關於使用單元格引用而不選擇它們之前的評論說的想法。

+1

謝謝大家的快速回復,這兩個解決方案都進行了一些調整。此外,感謝您閱讀有關避免選擇的建議。 – Jon

1

該代碼作爲子程序工作,因爲您有正確的工作表,因爲您的ActiveSheet property和subs允許您使用Range .Select方法和Range .Activate方法¹。在工作表上使用的函數需要知道它在哪個工作表上,並且選擇單元格不是批准的方法。

Public Function TraverseArea(Optional aRNG As Variant) As Double 
    Dim dAREA As Double, r As Long, rng As Range 
    dAREA = 0 

    With Application.Caller.Parent 
     If IsMissing(aRNG) Then Set aRNG = .Range("N2") 
     For Each rng In .Range(aRNG, aRNG.End(xlDown)) 
      If IsEmpty(rng) Or Not IsNumeric(rng) Or Not CBool(Len(rng.Offset(1, -1))) Then _ 
       Exit For 
      With rng 
       'Area = Area + (ActiveCell.Value * (ActiveCell.Offset(-1, -1).Value - ActiveCell.Offset(1, -1).Value)) 
       dAREA = dAREA + .Value2 * (.Offset(0, -1).End(xlDown).Offset(-1, 0).Value2 - .Offset(1, -1).Value2) 
      End With 
     Next rng 
    End With 

    If dAREA < 0 Then 
     dAREA = dAREA * -1 
    End If 
    dAREA = dAREA/2 
    TraverseArea = dAREA 

End Function 

Application.Caller可幫助查找函數所在的父級工作表。沒有選擇或激活單元格,但是通過提供行號,列號和Range.Offset property的某些操作使用直接尋址來循環。


¹How to avoid using Select in Excel VBA macros更多的方法從依靠選擇越來越遠,並激活,以實現自己的目標。