Excel VBA编辑器中的UDF仅在需要Double时返回零

时间:2016-02-15 02:02:48

标签: excel vba excel-vba

此功能用于计算闭合导线的面积。当作为子编写并分配给特定单元格时,子工作完美。但是,当用作函数时 - 如下所示 - 它仅返回零。为什么? '功能旨在容纳任意数量的导线侧

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

2 个答案:

答案 0 :(得分: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 :(得分: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