您的位置:首页 > 其它

在 Excel 中编写自定义函数——模拟 SUM 函数

2008-07-09 17:19 549 查看
编写自定义函数是为了处理数据,如何向自定义的函数(UDF)传递待处理的数据就成为开发者要考虑的问题。
就一般意义上的函数来说,参数列表通常是参数个数固定,类型明确的,比如下面的声明:
Public Function MyFunc1(name As String, age As Integer) As String

但是 Excel 里的函数有它的特殊性。我们在工作表里编写公式的时候,往往并不提供具体的数字或字符串,比如("张三",23),作为参数。在 Excel 里,我们习惯用单元格或单元格范围的引用来传递参数,像上面的例子,我们在调用函数时的表达方式可能是 =MyFunc1(A1,B1)。就上面的声明而言,如果我们只允许传递单一的单元格引用给参数是正确的,Excel 知道单元格引用的数据类型。

但有的时候,对于函数的某个参数,我们希望既可以传递单一的单元格,也可以传递一块单元格范围,增加函数的灵活性,就像 =Sum(A1) 和 =Sum(A1:A5) 都是可以的。这时候我们就不合适把参数声明为基本数据类型了,声明为 Excel 特有的数据类型 Range 就可以解决上面提到的问题,因为 Range 对象既可以是单一的单元格,也可以是一块单元格范围。

更进一步,如果我们希望参数列表是变长的呢?提供一个参数可以,提供两个三个也可以,参数的个数是任意的。

一种解决方法是用 Optional 关键词。带 Optional 关键词的参数不是必需的,我们可以给带 Optional 关键词的参数一个默认值,这样省略了该参数也没有什么关系了。

Public Function MyFunc2(name As String, Optional age As Integer =0) As String

但是用 Optional 关键词并不是真正的变长参数列表。我认为 Optional 关键词只是省去了用户的一些输入,在函数体内,参数的个数还是固定的。并且,如果我们希望提供的参数个数超出了定义的参数个数怎么办?Optional 是只能少不能多的,不是真正意义随心所欲的变长。

把参数声明为 Range 类型也是一种解决方法。Range 类型的参数可以是一个单元格,也可以是任意行列数的一块单元格。但是 Range 类型的参数也有个问题,我们传递单元格引用的时候是可行的,传递常数就会出错(Range 类型可以向下转换成基本类型,基本类型不能向上转换成 Range 类型)。我们希望在传递参数的数据类型上也保持一定的灵活性。

更贴近我们需求的解决方案是用 ParamArray 关键词。ParamArray 关键词允许我们传递任意个数的参数。并且,用 ParamArray 关键词声明的参数是 Variant 类型的数组,每个元素可以是各种数据类型。注意,ParamArray 关键词和 Optional 关键词是互斥的。

下面的例子是模拟 SUM 函数功能的自定义加总函数:

Function MySum(ParamArray numbers()) As Double

Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim argD As Integer
Dim rtn As Double
rtn = 0
argD = UBound(numbers)

For i = 0 To argD
If IsArray(numbers(i)) Then
If IsObject(numbers(i)) Then
For j = 1 To numbers(i).Rows.Count
For k = 1 To numbers(i).Columns.Count
If IsNumeric(numbers(i)(j, k)) Then
rtn = rtn + numbers(i)(j, k)
End If
Next k
Next j
Else
For j = LBound(numbers(i)) To UBound(numbers(i))
rtn = rtn + numbers(i)(j)
Next j
End If
Else
If IsNumeric(numbers(i)) Then
rtn = rtn + numbers(i)
End If
End If
Next i

MySum = rtn

End Function

做几点说明,用 ParamArray 关键词声明的参数数组只返回最高一级的维度,看上去像是一维的。这是因为用 ParamArray 关键词声明的参数数组里面的元素可以是很不同的,不一定要是一个几乘几的整齐的矩阵。比如,我们上面自定义的 MySum 函数可以这样调用 =MySum(A2:D4,2,{1,2,3,4})。

我们可以在代码里加入断点,然后从“Locals Window”查看 Numbers 这个数组的结构。如果我们尝试用 Numbers(i,j) 这样的表达式,反而会收到“Wrong number of dimensions”错误。

了解了用 ParamArray 关键词声明的参数数组的性质,就可以理解怎样遍历每个元素,并对每个元素进行不同的处理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐