我正在为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
答案 0 :(得分:1)
我认为您需要使用Application.ThisCell property
来执行此操作。根据MSDN:
Application.ThisCell-返回用户定义的单元格 函数作为Range对象调用。
让我介绍如何在简单的例子中使用它。 想象一下,我们在A:B列中有如下所示的数据,我们希望分别得到每行= A * B的结果。
在这种情况下,您需要以下功能,并以这种方式将其放在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
例如
然后,如果您转到电子表格并在任何行上键入Public Function MyTestFunction(ByVal arg1) As Variant
Set MyTestFunction = arg1
End Function
,您将从您传递给位于同一行的函数的列中收到等效值。
关于获得与=MyTestFunction(A:A)
相似的行为的第二个想法,你可以用
=A:A*B:B
例如