这个题目是受一个网友问题的启发,写在这里算是给自己留个记号. 第一, Worksheetfunciton.(excel自带的Function)与Application.Worksheetfunction.(excel自带的Function)在EXCEL环境下效果是一样的,也就是说Application可以省略,因为默认是EXCEL. 如果是在其他的OFFICE程序中调用EXCEL函数时需要加上Application,比如在Word中用VBA调用EXCEL函数,微软有这样的示例: Dim xlApp As Excel.Application Dim x, y As Integer Set xlApp = New Excel.Application x = ActiveDocument.ContentControls(1).Range.Text y = ActiveDocument.ContentControls(2).Range.Text ActiveDocument.ContentControls(3).Range.Text = _ xlApp.WorksheetFunction.Sum(x, y) (以下部分的讨论均只考虑EXCEL环境,不涉及其他任何程序,所以在用Worksheetfunction时,前面这个Application.是可以省略掉的) 第二,我们来看一下Application.(excel自带Function)与Worksheetfunction.(excel自带Function)有什么不同,其实在绝大多数情况下它们在使用上是一样的.网上通常认为主要区别在于对弹出错误的处理上.比如在用VLookup时: 程序1:
如果在A1:A100没有对应"hello"值,以上运行时会出现Run Time Error,所以容错处理上通常用On Error Resume Next, If Err.Number <> 0这样的结构. 程序2:
如果在A2:A10没有对应"hello"值,以上不会出现Run Time Error,会看到y值是: Error 2042. 在预想程序找不到到相应结果的"容错"处理上通常只要用: If IsError(y) = False 这样的语句就可以了. 另外的一个案例,是关于RoundDown函数结合声明Currency类型出现的:
SheetCredit not Rounded -0.775 WorksheetFunction.RoundDown: -0.77 Application.RoundDown: -0.78 理论上Rounddown的结果都应该是-0.77,但实际上Application.RoundDown结果为-0.78 奇妙的是,如果在声明变量时类型定义SheetCredit为Double类型,Application和Worksheetfunction的结果就是一样的了,都是0.77 SheetCredit not Rounded -0.774999999999999 WorksheetFunction.RoundDown: -0.77 Application.RoundDown: -0.77 除了数值范围外,Currency和Double最主要的区别是,前者不用浮点计算器,后者用,所以精度是不一样的(从0.775与0.7749999999999的区别上也可看出),但为什么Application和Worksheetfunction在处理对待-0.775上有不同的结果?更奇怪的是为什么Application.RoundDown是-0.78?事实上,我试了Application.Round, Application.RoundUp,结果都是-0.78! 也许是微软的另一个bug? 第三,前面的案例表明,Application与Worksheetfunction(或Application.Worksheetfunction)在VBA中的运用还是有区别的,虽然在绝大多数情形下我们似乎不需要在意,所以如果你看到某本VBA的书上说,以下三种写法可以互通,也不算什么错: Application.(excel自带Function) Application.Worksheetfunction.(excel自带Function) Worksheetfucntion.(excel自带Function) 我曾经看过一位微软MVP的观点,他讲了两点: 一是微软认为比较成熟的语法用法,会将它归档(中文可能翻译得不到位,英文是称为Documented),如果没有归档,是因为微软工程师们可能会在将来的版本中继续改进或增强或完善或抛弃它的用法.一般归档的用法微软在后期很少会改动,所以这位MVP建议大家在用EXCEL函数或VBA时,如果有可能,尽量用归档过的东西(微软的这个归档的列表在哪里,他没有说,我也不清楚),因为这些是微软自认为比较成熟的用法. 二是,微软在新推出Worksheetfunction的时候(我不知道是哪一年了),曾经表明将来会以这个为主,将来会淘汰对Application.(excel自带Function)这种用法的支持,要强制用户使用Application.Worksheetfunction.(excel自带Function),或者Worksheetfucntion.(excel自带Function),最关键的,是它把Worksheetfunction用法归档了,而Application直接带EXCEL Function的用法一直没有归档.所以为了避免将来因为版本升级造成代码多处改动的麻烦,这位MVP建议大家现在就养成用Worksheetfunction的习惯! 不过,事实上,直到2010版本为止,Application和Worksheetfunction的使用还在并存着,绝大多数用户也将它们混为一谈,微软什么时候会终止Application的直接调用,或者什么时候改变了想法,将Application的直接调用也归档,只有它自己知道了(?) 这个论坛很多人喜欢用数组,这就构成了第三个案例: 1) arr = Application.SumIf(Range("a2:a10000"), Array("B", "C", "G", "R"), Range("B2:B10000")) '运行正常 2) arr = WorksheetFunction.SumIf(Range("a2:a10000"), Array("B", "C", "G", "R"), Range("B2:B10000")) '运行时出现Run Time Error 13, 类型不匹配 初步结论是: a) 在SumIf这个函数上,Worksheetfunction是不支持数组条件的,如果将条件Array("B", "C", "G", "R")改为"B",是可以得到结果的 b) 在SumIf这个函数上,用Application直接调用,是支持数组条件的 c) 我猜Worksheetfunction不支持SumIf数组条件的可能原因是,因为Worksheetfunction相当于在Excel表格中直接输入,所以当在Excel中直接输入数组公式时,因为需要Ctrl + Shift + Enter三键并按才能得到结果,然后到VBA中用Worksheetfunction这个Object调用的时候,无法模拟CSE三键齐按,所以出现Run Time Error,而用Application直接调用,可能在程序后台有另外的内嵌计算方法直接支持数组模式,所以就避免了出错,这一点仍然与前面的Vlookup一例有相通之处. 结论是,Application.{excel function}与Worksheetfunction.{excel function}区别不大,但如果在你的代码里出现区别时,请不要太惊讶! 个人建议:如果你有个人喜好,那就保持代码习惯前后一致,如果用Application就一直用,如果用Worksheetfunction也就一直用,尽量不要在一段代码中混用这两种方法;如果你没有个人喜好,那么在两种方式都可正确运行时,尽可能只用Worksheetfunction,毕竟这是微软归档过的用法. |
|