从传递的列/行/范围VBA Excel中获取一个单元格

时间:2014-01-14 07:44:35

标签: excel vba excel-vba arguments

我正在为VBA中的excel编写用户定义的函数。

用户可以将整列/行传递给函数而不是一个单元格。如何获取位于同一行(对于列大小写)和同一列(对于行大小写)的单元格,其中函数是。

例如,当您在单元格中使用Excel编写时,例如C3,公式“= A:A * B:B”实际上计算A3 * B3。我想在我的UDF中拥有相同的行为。

让我们假设函数返回传递的参数,原因很简单。 此代码不起作用(对于列/行/范围返回#VALUE!):

Public Function MyTestFunction(ByVal arg1) As Variant
    MyTestFunction = arg1
End Function

我的选项如下,但我担心性能以及用户可能想要将值传递给公式而不是Range的事实。

Public Function MyTestFunction2(ByVal arg1 As Range) As Variant

    If arg1.Count = 1 Then
        MyTestFunction2 = arg1.Value
    Else
        ' Vertical range
        If arg1.Columns.Count = 1 Then
            MyTestFunction2 = arg1.Columns(1).Cells(Application.Caller.Row, 1).Value
            Exit Function
        End If

        ' Horizontal range
        If arg1.Rows.Count = 1 Then
            MyTestFunction2 = arg1.Rows(1).Cells(1, Application.Caller.Column).Value
            Exit Function
        End If

        ' Return #REF! error to user
        MyTestFunction2 = CVErr(xlErrRef)
    End If

End Function

你如何解决这个问题?


感谢有价值的评论代码略有更新,现在可以在其他公式中使用来过滤输入值。

Public Function MyTestFunction2(ByVal arg1) As Variant

    If Not TypeName(arg1) = "Range" Then
        MyTestFunction2 = arg1
        Exit Function
    End If


    If arg1.Count = 1 Then
        MyTestFunction2 = arg1.Value
    Else
        ' Vertical range
        If arg1.Columns.Count = 1 Then
            ' check for range match current cell
            If arg1.Cells(1, 1).Row > Application.Caller.Row Or _
                arg1.Cells(1, 1).Row + arg1.Rows.Count - 1 < Application.Caller.Row Then
                ' Return #REF! error to user
                MyTestFunction2 = CVErr(xlErrRef)
                Exit Function
            End If

            ' return value from cell matching cell with function
            MyTestFunction2 = arg1.Worksheet.Columns(1).Cells(Application.Caller.Row, arg1.Column).Value
            Exit Function
        End If

        ' Horizontal range
        If arg1.Rows.Count = 1 Then
            ' check for range match current cell
            If arg1.Cells(1, 1).Column > Application.Caller.Column Or _
                arg1.Cells(1, 1).Column + arg1.Columns.Count - 1 < Application.Caller.Column Then
                ' Return #REF! error to user
                MyTestFunction2 = CVErr(xlErrRef)
                Exit Function
            End If

            ' return value from cell matching cell with function
            MyTestFunction2 = arg1.Worksheet.Rows(1).Cells(arg1.Row, Application.Caller.Column).Value
            Exit Function
        End If

        ' Return #REF! error to user
        MyTestFunction2 = CVErr(xlErrRef)
    End If

End Function

2 个答案:

答案 0 :(得分:1)

我认为您需要使用Application.ThisCell property来执行此操作。根据MSDN:

  

Application.ThisCell-返回用户定义的单元格   函数作为Range对象调用。

让我介绍如何在简单的例子中使用它。 想象一下,我们在A:B列中有如下所示的数据,我们希望分别得到每行= A * B的结果。

enter image description here

在这种情况下,您需要以下功能,并以这种方式将其放在C列中:=MyTestFunction(A:A,B:B)

Function MyTestFunction(rngA As Range, rngB As Range)

    Dim funRow As Long
        funRow = Application.ThisCell.Row
    MyTestFunction = rngA(funRow) * rngB(funRow)

End Function

请注意,如果您通过其他VBA程序调用您的函数,Application.ThisCell将无效。

答案 1 :(得分:1)

在第一个代码段中,将MyTestFunction = arg1更改为Set MyTestFunction = arg1。还添加一个识别TypeName()的{​​{1}}的小机制,并确保该函数正在接收arg1类型对象。

Range

例如

enter image description here


然后,如果您转到电子表格并在任何行上键入Public Function MyTestFunction(ByVal arg1) As Variant Set MyTestFunction = arg1 End Function ,您将从您传递给位于同一行的函数的列中收到等效值。

关于获得与=MyTestFunction(A:A)相似的行为的第二个想法,你可以用

实现
=A:A*B:B

例如

enter image description here