在 Excel 中编写自定义函数——模拟 SUM 函数
2008-07-09 17:19
549 查看
编写自定义函数是为了处理数据,如何向自定义的函数(UDF)传递待处理的数据就成为开发者要考虑的问题。
就一般意义上的函数来说,参数列表通常是参数个数固定,类型明确的,比如下面的声明:
但是 Excel 里的函数有它的特殊性。我们在工作表里编写公式的时候,往往并不提供具体的数字或字符串,比如("张三",23),作为参数。在 Excel 里,我们习惯用单元格或单元格范围的引用来传递参数,像上面的例子,我们在调用函数时的表达方式可能是 =MyFunc1(A1,B1)。就上面的声明而言,如果我们只允许传递单一的单元格引用给参数是正确的,Excel 知道单元格引用的数据类型。
但有的时候,对于函数的某个参数,我们希望既可以传递单一的单元格,也可以传递一块单元格范围,增加函数的灵活性,就像 =Sum(A1) 和 =Sum(A1:A5) 都是可以的。这时候我们就不合适把参数声明为基本数据类型了,声明为 Excel 特有的数据类型 Range 就可以解决上面提到的问题,因为 Range 对象既可以是单一的单元格,也可以是一块单元格范围。
更进一步,如果我们希望参数列表是变长的呢?提供一个参数可以,提供两个三个也可以,参数的个数是任意的。
一种解决方法是用 Optional 关键词。带 Optional 关键词的参数不是必需的,我们可以给带 Optional 关键词的参数一个默认值,这样省略了该参数也没有什么关系了。
但是用 Optional 关键词并不是真正的变长参数列表。我认为 Optional 关键词只是省去了用户的一些输入,在函数体内,参数的个数还是固定的。并且,如果我们希望提供的参数个数超出了定义的参数个数怎么办?Optional 是只能少不能多的,不是真正意义随心所欲的变长。
把参数声明为 Range 类型也是一种解决方法。Range 类型的参数可以是一个单元格,也可以是任意行列数的一块单元格。但是 Range 类型的参数也有个问题,我们传递单元格引用的时候是可行的,传递常数就会出错(Range 类型可以向下转换成基本类型,基本类型不能向上转换成 Range 类型)。我们希望在传递参数的数据类型上也保持一定的灵活性。
更贴近我们需求的解决方案是用 ParamArray 关键词。ParamArray 关键词允许我们传递任意个数的参数。并且,用 ParamArray 关键词声明的参数是 Variant 类型的数组,每个元素可以是各种数据类型。注意,ParamArray 关键词和 Optional 关键词是互斥的。
下面的例子是模拟 SUM 函数功能的自定义加总函数:
做几点说明,用 ParamArray 关键词声明的参数数组只返回最高一级的维度,看上去像是一维的。这是因为用 ParamArray 关键词声明的参数数组里面的元素可以是很不同的,不一定要是一个几乘几的整齐的矩阵。比如,我们上面自定义的 MySum 函数可以这样调用 =MySum(A2:D4,2,{1,2,3,4})。
我们可以在代码里加入断点,然后从“Locals Window”查看 Numbers 这个数组的结构。如果我们尝试用 Numbers(i,j) 这样的表达式,反而会收到“Wrong number of dimensions”错误。
了解了用 ParamArray 关键词声明的参数数组的性质,就可以理解怎样遍历每个元素,并对每个元素进行不同的处理。
就一般意义上的函数来说,参数列表通常是参数个数固定,类型明确的,比如下面的声明:
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 关键词声明的参数数组的性质,就可以理解怎样遍历每个元素,并对每个元素进行不同的处理。
相关文章推荐
- 在 Excel 中编写自定义函数——返回多个值
- 在 Excel 中编写自定义函数——基础篇
- 利用eclipse编写自定义hive udf函数
- c程序:编写程序,其中自定义一函数,用来判断一个整数是否为素数,主函数输入一个数,输出是否为素数
- 作业五-设计一个程序计算输入的两个数的和与差,要求自定义一个函数 sum_diff(float op1, float op2, float *psum, float *pdiff),其中 op1 和 op2 是输入的两个数,*psum 和*pdiff 是计算得出的和与差.
- EXCEL自定义函数求1000以内的质数
- 将多个单元格的内容连接到一个单元格(Excel自定义函数)
- GetExcelDriver函数需要自定义
- 编写程序,自定义一函数,用来判断一个整数是否为素数,主函数输入一个数,输出是否为素数
- 使用VBA在EXCEL中插入图片自定义函数(网络URL/本地URL)
- phpExcel---自定义函数
- HIVE 编写自定义函数UDF
- Excel自定义函数
- 编写函数模拟掷骰子的游戏(两个骰子)。第一次掷的时候,如果点数之和为7或11则获胜;如果点数之和为2、3或12则落败;其他情况下的点数之和称为“目标”,游戏继续。在后续的投掷中,如果玩家再次掷出“目标
- 自定义Oracle聚集函数:模拟SUM,MAX,AVG
- EXCEL自定义考勤函数
- sqlserver中编写自定义函数中的返回值问题
- 提取一个单元格中的数字(Excel自定义函数)
- Excel非编程编写自动改卷试题用到的几个函数
- 如何编写分解因数的自定义函数?