【问题标题】:How to pass list of values to user defined function (UDF) in Excel如何将值列表传递给 Excel 中的用户定义函数 (UDF)
【发布时间】:2019-03-07 17:44:46
【问题描述】:
---------------------------------------
A                   B       C   D
---------------------------------------
Timestamp           Stock   Qty Price
---------------------------------------
01 February 2011    ST1     100 10
02 March 2013       ST1     900 11
01 February 2011    ST2     200 121
04 May 2014         ST1     250 15
02 March 2016       ST2     150 130
04 May 2018         ST2     250 140
08 September 2016   ST1     300 19
01 February 2012    ST3     400 190
11 November 2017    ST1    -400 20

我希望在 Excel 中创建一个名为 MyXIRR(日期为范围,值作为范围,余额为双精度,BalanceAsOn 日期)的函数

对于这个函数,我需要将时间戳列中的数据作为日期传递,数量 X 价格作为每个股票的值。 Balance 和 BalanceAsOn 是我将分别确定的。

例如 ST1

日期将在下方

01 February 2011    
02 March 2013       
04 May 2014     
08 September 2016
11 November 2017

值将低于

100
900
250
300
-400

我面临的问题是如何根据股票代码的过滤器传递值列表。

我不是 INDEX 或 MATCH 等方面的专家,但是当我尝试类似的东西时

=MyXIRR(INDEX(A1:A9,MATCH("ST1",B1:B9,0)), INDEX(C1:C9*D1:D9,MATCH("ST1",B1:B9,0)), 100.00, TODAY())

或按 Ctrl + Shift + Enter 将其用作数组,即

{=MyXIRR(INDEX(A1:A9,MATCH("ST1",B1:B9,0)), INDEX(C1:C9*D1:D9,MATCH("ST1",B1:B9,0)), 100.00, TODAY())}

然后在调试 MyXIRR 时,我在 Dates 中只得到一个值,在 Values 中得到一个值,即 2011 年 2 月 1 日和 100。我希望 MyXIRR 获得列表而不仅仅是第一个值。

怀疑我误用了 INDEX 我尝试了 IF 和 SUMPRODUCT 但我得到了#VALUE!以下两种情况均报错

=MyXIRR(IF(B1:B9="ST1",A1:A9,0), IF(B1:B9="ST1",C1:C9*D1:D9,0), 100.00, TODAY())

= MyXIRR(SUMPRODUCT((B1:B9="ST1"),A1:A9), SUMPRODUCT((B1:B9="ST1"),C1:C9*D1:D9), 100.00, TODAY() )

有人可以建议我做错了什么和/或建议前进的方向吗?

我正在使用 Excel for Mac 版本 16.16.2

下面是我的函数的样子

Public Function MyXIRR(Dates As Range, Trans As Range, Balance As Double,  BalanceAsOn As Date) As Double

Dim Cell As Range
 For Each Cell In Dates
    MsgBox Cell.Value
 Next Cell

MyXIRR = Dates.Count
End Function

这只循环一次,当我为 ST1 调用它时显示 01/02/2011

【问题讨论】:

  • 函数实际返回什么值?换句话说,Dates.Count 的值是多少?
  • 该函数必须返回一个数组才能使其成为返回的列表。你也可以使用字典,但这似乎有点过分了
  • 如果您想要一个数组作为输入,您需要更改条件:Public Function MyXIRR(Dates As Variant, Trans As Variant,... 并且 INDEX/MATCH 将始终只返回第一个匹配项,因此请使用 IF 作为数组公式。

标签: excel vba excel-udf xirr


【解决方案1】:

[请注意,以下解决方案尚未在 Mac 版本的 Excel 上进行测试。]

要仅传递与“ST1”对应的值,首先您需要将 Dates 和 Trans 声明为 Variant,正如 Scott 已经提到的,然后相应地更改函数的主体...

Public Function MyXIRR(Dates As Variant, Trans As Variant, Balance As Double, BalanceAsOn As Date) As Double

     Dim currentDate As Variant

     For Each currentDate In Dates
         MsgBox currentDate
     Next currentDate

     MyXIRR = UBound(Dates)

End Function

那么就可以使用下面的公式了,需要用CONTROL+SHIFT+ENTER确认,不能只用ENTER...

=MyXIRR(INDEX(A2:A10,N(IF(1,SMALL(IF(B2:B10="ST1",ROW(B2:B10)-ROW(B2)+1),ROW(INDIRECT("1:"&COUNTIF(B2:B10,"ST1"))))))),INDEX(C2:C10*D2:D10,N(IF(1,SMALL(IF(B2:B10="ST1",ROW(B2:B10)-ROW(B2)+1),ROW(INDIRECT("1:"&COUNTIF(B2:B10,"ST1"))))))),100,TODAY())

如果操作正确,Excel 将自动在公式周围放置花括号 {...}。

【讨论】:

  • 您的 index(n()) 可以简化为简单的 IF IF(B2:B10="ST1",A2:A10)IF(B2:B10="ST1",C2:C10*D2:D10)
  • @ScottCraner 是的,非常正确。但是,在这种情况下,最好将整个范围以及标准简单地传递给 MyXIRR,然后处理代码中的所有内容。这样,您将传递一个范围而不是一个数组,并且不需要使用 CSE 确认公式。而且,希望它应该更有效率。
  • 就个人而言,我会这样做,我会将条件和条件范围设为一个新列。所有好的建议。基本上错误是在需要数组时尝试传递范围。
  • @ScottCraner 是的,这里也一样。我只提供了我的解决方案,因为我的理解是 OP 只想将相关值传递给函数。
  • 我尝试了这个解决方案,但没有用。我得到#VALUE!。现在我将在函数中传递整个范围和搜索条件,并在 VBA 代码中计算 XIRR。稍后将返回解决此数组问题。
【解决方案2】:

试试这个:

Public Function MyXIRR(Dates As Range, Trans As Range, Balance As Double, BalanceAsOn As Date) As Double

    Dim Area as Range    
    Dim Cell As Range

    For Each Area in Dates.Areas
        For Each Cell In Area
            MsgBox Cell.Value
        Next Cell
    Next Area

    MyXIRR = Dates.Count
End Function

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-23
    • 1970-01-01
    相关资源
    最近更新 更多