【问题标题】:UDF with infinite parameters具有无限参数的 UDF
【发布时间】:2017-08-29 07:45:31
【问题描述】:

我正在编写一个用户定义函数 (UDF),它以一些单元格作为参数。 这些单元格包含相同的数据,但精度不同;该函数显示可用的最佳精度。

函数的参数按精度升序写入。

这是一个例子:

+---+-----------------+---------------------+
|   |        A        |          B          |
+---+-----------------+---------------------+
| 1 | Best            | =get_best(B5;B4;B3) |
| 2 |                 |                     |
| 3 | provisional     | 1                   |
| 4 | definitive      | 2                   |
| 5 | etched in stone | 12                  |
+---+-----------------+---------------------+

函数显示 12,因为单元格 B5 中的信息比 B4 和 B3 具有更好的价值。因此,在公式参数中,B5 写在 B4 和 B3 之前。

我的UDF代码如下:

Public Function get_best(r1 As Range, r2 As Range, r3 As Range) As Variant

    get_best = ""

    If r3.Value <> "" Then get_best = r3.Value Else
    If r2.Value <> "" Then get_best = r2.Value Else
    If r1.Value <> "" Then get_best = r1.Value

End Function

有效!但我想对其进行编辑,以便它可以像=get_best(B7;B6;B5;B4;B3) 那样进行无限量的调整。 我怎么能这样做?

有用的评论: “单元格 B5 比 B4 和 B3 具有更好的值”意味着,例如,在 B3 中,您有 12 个月前计算的预测值。在单元格 B5 中,您有有效值和测量值。因此,当您拥有 B5 时,您不再需要 B3,因为“B5 比 B3 更好”

【问题讨论】:

  • Public Function get_best(r1 As Range, r2 As Range, r3 As Range, Optional r4 as Range, Optional r5 as Range, etc... ) As Variant怎么样?
  • FWIW - 这些 If 语句上的 Else 是多余的 - 如果有您需要的代码,您只需在单行 Ifs(甚至在块 Ifs 中)包含 Else当条件为False时执行。

标签: vba excel user-defined-functions excel-udf


【解决方案1】:

如果 best 值始终位于 Range 的底部,但您不确定要搜索的列中的行数,则可以使用:

Public Function get_best(rng As Range) As Variant

    Dim lngLastRow As Long

    lngLastRow = rng.Parent.Cells(rng.Parent.Rows.Count, rng.Column).End(xlUp).Row
    get_best = rng.Parent.Cells(lngLastRow, rng.Column).Value

End Function

【讨论】:

  • 该功能有效!唯一的一点是,如果我将公式写在 B1 中,将值写在 B3:B5 中,它就会起作用。例如,如果我在 B7 中编写相同的公式,我会从 Excel 中得到一个循环引用错误。
  • 是的 - 如果您的公式在 B7 中,您只能将 B3:B6 传递给函数,而不是 B:B。如果您想传递完整的列(我认为这是您想要的“无限”参数列表),那么您必须将带有函数的单元格放在另一列中。 HTH。
  • 当我问这个问题时,我正在考虑以特定顺序为单个单元格提供公式,但这个解决方案没问题,适用于我的应用程序。
【解决方案2】:

根据您展示的示例,这对您不起作用吗?

Public Function get_best(ByVal Rng As Range) As Variant
    get_best = Application.Max(Rng)
End Function

那你可以这样试试……

=get_best(B3:B5)

【讨论】:

  • 对不起,答案是否定的。这取范围的最大值,但我想要具有最佳精度的值。如果示例是 B3=5; B4=6 和 B5=4 它应该显示 4(因为 B5 比 B4 好于 B3)。
  • 在该示例中,为什么 4 比 5 或 6 更精确?
  • 因为“确定”值比“临时”值更精确。我在第一篇文章(=问题)中添加了几句话来解释它。希望现在应该更清楚了。
【解决方案3】:

我不明白您所说的 “单元格 B5 比 B4 和 B3 具有更好的价值”是什么意思。您的代码会查看哪个单元格包含从参数中最后一个开始的值。

您可以使用参数数组添加任意数量的范围:

Public Function get_best(ParamArray Ranges()) As Variant

    Dim x As Long

    For x = UBound(Ranges) To LBound(Ranges) Step -1
        If Ranges(x) <> "" Then
            get_best = Ranges(x).Value
            Exit For
        End If
    Next x

End Function

【讨论】:

  • “单元格 B5 比 B4 和 B3 具有更好的值”意味着,例如,在 B3 中,您具有 12 个月前计算的预测值。在单元格 B5 中,您有有效值和测量值。因此,当您拥有 B5 时,您不再需要 B3,因为“B5 比 B3 更好”。
  • 啊,好的。在那种情况下,Excel 如何知道哪个是预测值,哪个是有效值和测量值?如果它只是单个列中的最后一个值,那么@user3598756 给出的答案将是要找的答案。我的将给出单元格列表中的最后一个单元格 - 只需选择最后一个单元格并忽略其余单元格会更容易(即将您的函数更改为 =B5)。 :)
【解决方案4】:

您可以避免以这种方式传递任何range 参数

Public Function get_best() As Variant
    get_best = Cells(Rows.Count, Application.Caller.Column).End(xlUp).Value
End Function

如果你必须指定一个(连续的)范围,你可以如下操作:

Public Function get_best(r As Range) As Variant
    With r
        If WorksheetFunction.CountA(.Cells) > 0 Then get_best = .Cells(.Rows.Count + 1).End(xlUp).Value
    End With
End Function

【讨论】:

  • 是的,但是第一个给我一个错误。 Excel 给了我一个错误,因为 UDF 不接受参数,然后 VBA 编辑器说“参数不是可选的”。第二个给我“#VALUE!”如果我给出一系列单元格作为参数,或者我给出几个单元格。
  • 1) 第一个代码有意设计(并测试)不接受任何参数:只需从要扫描范围上方的单元格调用该 UDF 2) 我不t 得到第二个代码的问题:在这种情况下,UDF is 设计(和测试)接受 "(contiguous) range" 作为参数,那么你怎么办表示“单元格范围”“几个单元格”抛出问题?
  • @Nicolaesse,感谢您对我在上一条评论中给出的代码说明的反馈。谢谢
猜你喜欢
  • 2018-10-02
  • 1970-01-01
  • 1970-01-01
  • 2020-06-01
  • 2011-11-06
  • 2016-01-13
  • 1970-01-01
  • 2016-02-06
  • 1970-01-01
相关资源
最近更新 更多