排序和过滤
阅读本节时,如果您打开随书光盘Samples\Chap02目录下的SortFilterExample.htm文件。您会发现这个例子很有用。本节展示的代码和描述的特定环境来自这个文件。
电子表格组件支持Excel中的基础的排序和过滤功能,并且通过编程模型和用户界面来提供这些功能。然而,在电子表格的用户界面中,排序和过滤的功能比起Excel有某种程度的增强。让我们来看一个例子。
DHTML探险
属性工具箱是由两位OWC小组的天才程序员,Eric Matteson和Cesar Alvarez开发的不可思议的杰作,属性工具箱也证明了试图使用DHTML来模仿Office的用户界面风格是一件困难重重的事。早期,我们坚持认为我们应该使属性工具箱尽可能地和标准的Office用户界面相似,Eric和Cesar也的确花费了数月的时间来改变HTML和IE浏览器,使得它能符合需求。大多数人都不相信结果竟然就在HTML中。然而,因为考虑到虽然一般人都可以很有效的使用web站点,但还是会被Office应用程序中的许多高级对话框所迷惑,所以关于使用HTML来模拟Office用户界面是否使得控件更易于使用的争论依然很突出。
对于那些希望在web页面中使用Office Web Components的开发者们,我的建议是不要浪费时间企图将HTML融入到传统的微软窗体应用程序的界面中,而应该利用HTML的简洁和动态布局的优势来为您的应用程序开发一个更加自然和易于使用的界面。
假设您已经开发了一个用于列出您当前的产品线的电子表格, 表格中显示了每一个产品的单价,库存数量,和定购数量,还有一个给出了销售率的计算列,用于显示潜在的价值。现在用户需要根据产品的潜在价值对产品列表进行降序排列。用户可以在电子表格用户界面中,简单的选择需要排序的区域(或者在区域中选择任意的一些单元),并点击降序工具条按钮。当按钮被点击时,一个Excel中没有的菜单在按钮下方显示出来,如图2-2所示。
图2-2 使用中的电子表格组件用户界面
用户们在对Excel区域排序时所遇到的常见问题之一就是选择要排序的区域和选择根据哪一列进行排序。电子表格组件让用户能够方便的选择需要排序的区域,然后在用户点击工具条上的升序或降序排序按钮时,显示一个列名的列表,使用户能够选择根据哪一列进行排序。通过Range对象的Sort方法,也可以使用排序功能。它使开发人员可以在用户单击或者双击一个列标头时方便地完成一个列表的排序。
您可以已经注意到电子表格组件一次只能根据一列来对列表进行排序。Excel提供了一个排序对话框,可以让您同时根据最多三个关键列进行排序(例如,是否根据种类排序,然后根据发货人排序,最后根据潜在价值排序)。电子表格组件没有完成这个功能的用户界面,但是底层的引擎是支持这个功能的。您可以使用下列函数模仿多列的排序。
实现多列排序的技巧在于,实际上是按照被排序列所定义次序的相反次序执行排序动作。例如,如果您需要先根据类别进行排序,然后再根据发货商进行排序,函数则会首先根据发货商排序列表,然后再根据类别进行排序。当电子表格根据一个新列排序列表时,新列的每一项(新列中相同列值的一组行)中,之前根据另一列进行排序产生的次序将保持不变。我们刚才阅读的函数接收三个参数:一个需要排序的区域,一个列编号的数组,一个方向值的数组(降序或升序)。函数降序遍历这两个数组,从而实现了多列排序的效果。请注意,函数还使用了BeginUndo和EndUndo方法来将所有的排序操作组合在一个撤消动作块中,这样当用户选择撤消命令时,这些排序动作就会被一起撤消。
电子表格组件也支持一种新的自动过滤的用户界面。组件中的过滤函数和Excel中的过滤函数相似,但是组件用户界面中的自动过滤下拉列表有一些不同的地方。假设您需要从图2-2中我们刚才查看过的产品列表中,过滤掉一些产品类别来观察它会怎样影响高潜在价值的产品。开发者或用户可以打开自动过滤功能,在类别列上点击自动过滤箭头,就会看到图2-3所示的界面。
图2-3. 电子表格组件的自动过滤用户界面
在Excel中,可以非常方便的选择单个项,然而,选择多项则需要使用高级自动筛选对话框,当您只是想要排除四五项时,这个操作就会十分费劲。而在电子表格组件中,自动过滤下拉列表为每一项都提供了一个简化复选框,在顶部还有一个”显示所有”项,使您能够快速切换所有项的状态(选择或不选择)。
机敏的读者会发现电子表格组件中的自动过滤下拉列表没有包括Excel中很有用的两个设置选项。例如,您找不到”前10位”的选项,这个选项使您能够快速过滤,得到前10位(或者前n位)的项。您也找不到”自定义”的选项,这个选项允许您完成比简单的包含或不包含的过滤复杂得多的过滤功能。很遗憾,这些更高级的功能还没有包含在电子表格组件中。不过,您可以通过调用电子表格控件的编程模型来容易得模拟这些功能。
可以使用下列函数来模拟”前n位”的过滤功能:
“前N位”过滤功能似乎很简单,只要先排序,然后查看最开始的N行即可。但是真正的”前N位”过滤功能可能会返回超过N行的结果,因为它实际上的意思是”包括前N位的值的那些行”。如果在排序后,第10,11位的值相同,那么”前10位”过滤会将这些产品一起返回,因为它们都在前10位的值当中。还有,上述代码通过简单的改变排序方向(升序和降序)实现了过滤出前N位和后N位的功能。
同样地,您可以通过使用下面所示的函数来模拟基于表达式的过滤功能:
上述函数使用文档对象模型(DOM)中名为execScript的方法执行表达式(DOM是为Internet Explorer中的脚本提供的编程模型)。这个方法将字符串形式的脚本代码传递给动态引擎脚本(在这个例子中,是VBScript)来计算。之后脚本代码将表达式的结果存储在一个全局变量中,以便结果能够被用来判断表达式的真假。如果表达式为真,该行将会被包含在过滤后的集合中;如果为假,该行将被排除。
另外,您也可以使用电子表格组件的工作表对象中的Eval方法来计算表达式。Eval使用电子表格组件的函数库和表达式计算器,它可以代替动态脚本引擎,这就意味这在IE之外的容器中它会非常有用,另外当您希望可以让用户在表达式中使用电子表格的函数或区域的引用时它也会很有用。然而,动态脚本引擎可以提供一个强大的表达式计算器。还有,它允许您使用其它的脚本语言,例如ECMA脚本(也被称为JavaScript)。