【问题标题】:Consistently returning the entire array in a VBA UDF?始终在 VBA UDF 中返回整个数组?
【发布时间】:2015-10-29 14:54:01
【问题描述】:

我编写了以下简单的 VBA 函数来计算两个量之间的线性级数,并以数组的形式返回该级数:

Public Function applyLinear(startAmount As Double, stopAmount As Double, Intervals As Integer)
    Dim diff As Double
    Dim resultArr() As Double
    Dim counter As Integer    
    diff = stopAmount - startAmount
    ReDim resultArr(Intervals, 0)
    resultArr(0, 0) = startAmount
    For counter = 1 To (Intervals)
        resultArr(counter, 0) = resultArr(counter - 1, 0) + diff / Intervals
    Next ' counter
    counter = 0
    applyLinear = resultArr
End Function

不幸的是,实际输出到工作表的内容完全取决于调用上述公式的单元格数。(这意味着用户很容易错误地应用函数!)

如何确保整个数组在all情况下输出到工作表?

编辑:或者更确切地说,当从单个单元格调用上述 UDF 时,如何让 VBA 输出整个数组?

编辑 2:更多说明。如果在调用它时使用了“intervals+1”行,则该函数会按预期工作。但是,如果(例如)用户在间隔 > 4 时不小心从 4 行调用函数,则会出现问题。在这种情况下,只有 resultArr 的前四个元素输出到工作表,这是一个问题,因为它不会表示完整的线性级数。

【问题讨论】:

  • 您是否尝试在 udf 开头将变量设置为零?
  • @汤姆。我不太了解?该函数确实按预期工作,但前提是用户从“intervals+1”单元格调用该函数。
  • 也许添加一个检查以查看是否已输入 UDF 的范围 = "intervals + 1"。然后,不要输入值,而是让 UDF 读取类似“错误 - 必须输入” & “间隔 +1” “ CELLS INSTEAD OF “ & #OF_CELLS_ENTERED
  • @ Grade 'Eh' Bacon - 这绝对是一个选择,至少不会误导用户!理想情况下,尽管我坚持以某种方式让它与一个“输入单元”一起工作。我怀疑有某种神秘的 VBA 解决方法可以做到这一点,因为 Bloomberg 似乎已经在他们的 Excel 插件中管理它。
  • 看看下面我的建议;我试图解决这两种方法 - 通过根据输入的单元格数更改值,或者在输入错误的单元格数时简单地显示错误消息。如果我误解了需要输入多少个单元格(间隔?或间隔 + 1?),那么这应该很容易解决。

标签: vba excel user-defined-functions


【解决方案1】:

在研究如何执行我在上面评论中的建议时,我发现了一些关于 Application.Caller 函数的有趣信息,它允许您访问输入 UDF 的单元格的属性。请参见此处:@987654321 @

根据 cpearson [http://www.cpearson.com/excel/returningarraysfromvba.aspx] 的一些进一步指导,这是执行此操作的一种方法

Public Function applyLinear(startAmount As Double, stopAmount As Double, Intervals As Integer)

Dim diff As Double
Dim resultArr() As Double
Dim counter As Integer
ReDim resultArr(Intervals, 0)

If Application.Caller.Rows.Count <> Intervals + 1 Then

    applyLinear = "ERROR - MUST ENTER THIS FORMULA IN " & Intervals + 1 & " CELLS"

Else

    diff = stopAmount - startAmount
    resultArr(0, 0) = startAmount

    For counter = 1 To (Intervals)
        resultArr(counter, 0) = resultArr(counter - 1, 0) + diff / Intervals
        TotalityCheck = TotalityCheck + resultArr(counter, 0) 'builds in by the end of the loop the total array value
    Next ' counter


    applyLinear = resultArr
End If

End Function

虽然,既然您已经使用了 Application.Caller 函数,您或许可以更简单地执行此操作,无需用户输入间隔数 - 而是将间隔数定义为application.caller.rows - 1,如下:

Public Function applyLinear(startAmount As Double, stopAmount As Double)

Dim diff As Double
Dim resultArr() As Double
Dim counter As Integer
Dim Intervals As Integer
ReDim resultArr(Intervals, 0)

Intervals = Application.Caller.Rows.Count - 1

    diff = stopAmount - startAmount
    resultArr(0, 0) = startAmount

    For counter = 1 To (Intervals)
        resultArr(counter, 0) = resultArr(counter - 1, 0) + diff / Intervals
        TotalityCheck = TotalityCheck + resultArr(counter, 0) 'builds in by the end of the loop the total array value
    Next ' counter


    applyLinear = resultArr


End Function

【讨论】:

  • 谢谢,我可能会使用这个没有间隔的版本作为参数。只需将 ReDim 向下移动,它就像一个魅力。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-09
  • 1970-01-01
  • 1970-01-01
  • 2019-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多