UDF:处理范围和可变数量的参数

Posted

技术标签:

【中文标题】UDF:处理范围和可变数量的参数【英文标题】:UDF: Handling ranges and variable numbers of arguments 【发布时间】:2013-06-28 10:16:56 【问题描述】:

我正在尝试编写一个 UDF(用户定义函数)来创建非数字数据的平均值(我将其转换为数字形式,然后在最后再次返回)。如果我列出单个单元格,我可以让 UDF 工作;我得到一个#VALUE!如果我尝试引用一系列单元格,则会出错。可能会同时处理范围和单个单元格。

有什么想法吗?

到目前为止的代码如下。

Function avlvl(ParamArray av() As Variant)
Dim a As Integer
'creates an average ks3 level from data in format "5a"
a = 0
n = 0
total = 0
Do While a < UBound(av()) + 1
   'ignore blank or zero cells
    If av(a) = 0 Or av(a) = "" Then
        a = a + 1
    Else
       'convert data into numeric value - split into level and sub level
        level = Val(Left(av(a), 1))
        sl = Right(av(a), 1)
        If sl = "c" Then
            sublevel = 0
        ElseIf sl = "C" Then
            sublevel = 0
        ElseIf sl = "b" Or sl = "B" Then
            sublevel = 1 / 3
        ElseIf sl = "a" Or sl = "A" Then
            sublevel = 2 / 3
        Else
            sublevel = 0
        End If
       'score is numeric value of the data
        score = level + sublevel
       'total is teh toatl of the cells so far
        total = total + score
        a = a + 1
        n = n + 1
    End If
Loop
ave = total / n
'reconvert into format level and sublevel (a,b,c)
averagelevel = Application.WorksheetFunction.RoundDown(ave, 0)
asl = ave - averagelevel
If asl < 0.17 Then
    averagesublevel = "c"
ElseIf asl < 0.5 Then
    averagesublevel = "b"
ElseIf asl < 0.84 Then
    averagesublevel = "a"
ElseIf asl < 1 Then
    averagelevel = averagelevel + 1
    averagesublevel = "c"
Else
    averagesublevel = "c"
End If

avlvl = averagelevel & averagesublevel

End Function

【问题讨论】:

我怀疑发生的事情是范围作为 Range 类型的单个对象传入,而您的代码试图将其视为数组传入。如果是这样,您需要测试 PamArray 元素的类型;如果第一个元素是 Range 类型,则将其分配给数组进行处理。另外,我是否正确理解您可能同时将范围和单个单元格传递给函数。 你知道我是怎么纠正的吗? 您应该将其元素分配给函数内部的另一个数组,而不是直接对 PamArray 进行操作。测试 PamArray 的每个元素的类型:如果是单个单元格,则直接将其放入新数组中;如果它是一个范围,您应该循环遍历它,将每个单元格的值分配给新数组。然后对新数组进行操作。 谢谢。这样就解决了。 【参考方案1】:

发生的情况是范围作为 Range 类型的单个对象传入,而您的代码试图将其视为数组传入。

最好的方法是在函数体中创建一个新数组,然后将范围内的元素分配给新数组。您需要测试 ParamArray 元素的类型。如果元素是String类型,则直接放入新数组中;如果元素是 Range 类型,则循环遍历它,将其单元格值分配给新数组。

然后您将对新数组进行处理。

以下代码提供了传递范围以及单个单元格或值的机制。我没有包含你的代码,但已经指明了它的去向。

Function avlvl(ParamArray av() As Variant) As Variant

    Dim a As Integer
    Dim i As Long
    Dim avArr()
    Dim element As Variant

    a = 0
    i = 0
    Do While a < UBound(av) + 1
        If TypeName(av(a)) = "String" Then
            avArr(i) = av(a)
            i = i + 1
        ElseIf TypeName(av(a)) = "Range" Then
            For Each element In av(a)
                ReDim Preserve avArr(0 To i)
                avArr(i) = element
                i = i + 1
            Next
        Else
            avlvl = CVErr(xlErrValue)
            Exit Function
        End If
        a = a + 1
    Loop
    i = 0
    Do While i < UBound(avArr) + 1
        '...
        'now process the elements of avArr()
        '...
        i = i + 1
    Loop
End Function

【讨论】:

【参考方案2】:

如果您有一个不相交的单元格范围,并且您想将它们传递给 UDF,一种方法是创建一个定义名称并将其作为单个参数传递给 UDF。

【讨论】:

我想让它尽可能地类似于 average() 和 sum() 函数 - 我希望能够将该函数提供给学校的其他老师使用跨度>

以上是关于UDF:处理范围和可变数量的参数的主要内容,如果未能解决你的问题,请参考以下文章

Spark Sql udf,参数数量可变

创建具有可变数量参数的 CLR UDF

pyspark udf 的可变参数数量

Spark UDF 函数怎么实现参数数量变化?

Excel UDF 接受范围和数组作为参数,如“SUM”

Spark UDF 作为函数参数,UDF 不在函数范围内