使用单元格相对于活动单元格的内容作为自定义函数

时间:2016-05-09 07:55:12

标签: excel excel-vba excel-formula vba

我正在尝试在Excel Visual Basic编辑器中创建我的第一个用户定义函数。我在带有OS X El Capitan版本10.11.1的Macbook Pro 2011上使用Excel 2011

我正在创建一个工作簿,该工作簿将使用我的函数来计算4 Division格式的桶形竞赛结果。分歧如下:

第一个分区或“1D”是最快的时间,最快时间可达0.499秒。

第二个分区或“2D”是最快时间0.5到0.999秒之间的下一个最快时间。

第三次划分或“3D”时间介于最快时间的1秒到1.499秒之间。

最后,第四次分裂或“4D”时间是最快时间的1.5秒或更多秒。

这是我必须计算这些划分的当前代码:

Function DIV(pVal)
If pVal = "Z" Then
DIV = ""
ElseIf pVal = 999 Then
DIV = "DQ"
ElseIf pVal > 100 Then
DIV = "NT"
ElseIf pVal < (Range("B2") + 0.5) Then
DIV = "X1D"
ElseIf ActiveCell.Offset(-1, 0) = "X1D" And pVal < (Range("B2") + 1) Then
DIV = "2D"
ElseIf pVal < (Range("B2") + 1) Then
DIV = "X2D"
ElseIf pVal < (Range("B2") + 1.5) Then
DIV = "X3D"
ElseIf pVal > (Range("B2") + 1.499) Then
DIV = "X4D"
Else
DIV = "Incorrect"
End If
End Function

现在,我只想在每个部门中第一次产生“2D”,“3D”和&amp; “4D”和每个分区中的其余时间产生“X1D”,“X2D”,“X3D”和&amp; “X4D”,因为我将应用条件格式,以便以“X”开头的任何内容都会以白色文本显示,因此在查看时看不见,但是,当我继续前进时,我仍然可以将它用于将来的功能到每个部门的位置。

所以例如,我正在研究2D,我希望所有时间都在最快时间0.5到0.999秒之间返回“X2D”的结果,除了第一个意味着它上面的单元格会说“X1D”。

上面代码中的所有内容都在工作,但应该返回“2D”的ElseIf除外。它会以虚假的方式返回并继续前进到下一个ElseIf,然后返回“X2D”。

我一次删除了部分代码并对其进行了测试。我已将问题缩小到ActiveCell.Offset部分。

过去三天我在互联网上搜索过,试图弄清楚我错过了什么,我找不到它。以下是我尝试根据我在网上发现的内容进行输入的所有方法,到目前为止还没有任何效果。

ElseIf ActiveCell.Offset(rowOffset:=-1, columnOffset:=0) = "X1D" And pVal < (Range("B2") + 1) Then DIV = "2D"

ElseIf pVal < (Range("B2") + 1) And ActiveCell.Offset(-1, 0) = "X1D" Then DIV = "2D"

ElseIf pVal < (Range("B2") + 1) And ActiveCell.Offset(-1, 0).Select = "X1D" Then DIV = "2D"

ElseIf pVal < (Range("B2") + 1) And ActiveCell.Offset(-1, 0).Range = "X1D" Then DIV = "2D"

ElseIf pVal < (Range("B2") + 1) And ActiveCell.Offset(-1, 0).Activate = "X1D" Then DIV = "2D"

我根据别人在另一个网站上建议的内容尝试了另一种编码方式,就是这样:

Function DIV(pVal)

If pVal = "Z" Then DIV = ""
If pVal = 999 Then DIV = "DQ"
If pVal > 100 Then DIV = "NT"
If pVal < (Range("B2") + 0.5) Then DIV = "X1D"
If ActiveCell.Offset(-1, 0) = "X1D" And pVal < (Range("B2") + 1) Then DIV = "2D"
If pVal < 100 Then DIV = "Correct"
If DIV = "" Then DIV = "Incorrect"

End Function

当我尝试这个时,它使整个功能停止工作,所有结果都恢复为“正确”。

我完全不知道应该怎样做才能解决这个问题,如果有人有任何建议我会非常感激。

谢谢!

编辑** 该功能仅用于所有C列,C1和C组除外。 C2,因为C1是标题单元格,C2总是1D。

如何使用该功能的具体示例:

假设有12次,每个师3次。

总是在B2中的快速时间是15.000。

B5中的时间是15.5,这是第一次2D时间。

该函数在C5中,应首先询问B5是否为“Z”,如果为真,则应将单元格留空,如果不为真,则应询问B5是否为= 999,如果为真,则应返回“DQ”如果不是真的,那么它应该询问B5是否> 100,如果为真,它应该返回“NT”,如果不是真的那么它应该询问B5是否&lt; B2 + 0.5,如果为真,它应该返回“X1D”,如果不是真的那么它应该询问B5是否&lt; B2 + 0.999 AND C4 =“X1D”,如果为真,则应返回“2D”,如果不是,则应询问B5是否为&lt; B2 + 0.999,若为真,则应返回“X2D”,如果不是真的,则应继续询问下一个分区。如果我能弄清楚如何用第二部门做到这一点,我可以从中学习并能够完成其他部门,并希望为我希望工作簿做的其他事情创建新的功能。

我希望这有帮助!

1 个答案:

答案 0 :(得分:0)

您需要重新设计函数的逻辑,但在设计UDF时,还要将所有变量传递给,而不是在函数中分配。这就是我认为你的功能应该是这样的:

Public Function DIV(pVal As Double, testRng As Range, testX1D As Range) As String

    Dim ret As String

    If testX1D.value = "X1D" Then
        If pVal < testRng.value + 1 Then
            DIV = "2D"
            Exit Function
        End If
    End If

    Select Case CVar(pVal)
        Case "Z":                           ret = vbNullString
        Case 999:                           ret = "DQ"
        Case Is > 100:                      ret = "NT"
        Case Is < (testRng.value + 0.5):    ret = "X1D"
        Case Is < (testRng.value + 1):      ret = "X2D"
        Case Is < (testRng.value + 1.5):    ret = "X3D"
        Case Is > (testRng.value + 1.499):  ret = "X4D"
        Case Else:                          ret = "Incorrect"
    End Select

    DIV = ret

End Function

值得注意的是,在以这种方式比较值时,您必须非常仔细地指定测试的顺序。例如,如果此方案中pVal的值为999

Case 999:                           ret = "DQ"
Case Is > 100:                      ret = "NT"

它将返回“DQ”,因为这是第一次测试,但是如果这些是另一种方式:

Case Is > 100:                      ret = "NT"
Case 999:                           ret = "DQ"

你会得到“NT”,因为pVal 大于100.只是要记住一些事情......

使用此UDF

示例,公式在C5中输入,其中pVal是B5中的值

=DIV(B5,C4,$B$2)

(注意B2的绝对参考)