很多朋友在试图用VFP控制Excel都有过无从着手困惑,不知道该去调用哪些过程、方法、函数。
其实进入Excel后,如果我们按Alt-F11,打开Excel自带的Visual Basic编辑器,然后按F2,在对象浏览器里,可以找到许多有用资源。如下图。
接下来就好办了,不停地与帮助文件对照,查找属性、方法的详细说明。
题外话,我总觉得微软编程序不够厚道,类、类的属性、类的实例经常使用同一个名字,例如类Range、Sheets、WorkBooks,都与类Application的一个属性同名,而且这些属性又恰好都是这些同名类,把我搞得晕晕糊糊,熟了之后才反应过来,哦,原来是不同的东西。有人夸这是C++灵活性的体现,我是不太喜欢这种编码方法,也许高手能挥洒自如吧。
打住,回头看看Excel里与排序有关的类、方法和函数。
Range类里有这么两个方法Sort 和 SortSpecial,从字面上看估计和排序有关,进入帮助看看。
-
关于Sort,它第一句话是这么说的:“对数据透视表、单元格区域或活动区域(如果指定区域仅包含一个单元格)进行排序”。看样子找对了。接下来是调用说明:
expression.Sort(Key1,Order1,Key2,Type,Order2,Key3,Order3,Header,OrderCustom,MatchCase,Orientation,SortMethod,DataOption1,DataOption2,DataOption3)
用无特定指向的expression来表示Sort的宿主,说明许多类会拥有这一属性,不单是Range类。各参数说明还是比较容易理解的,不逐一分析,说说重点。- 参数Key1,第一个排序字段。Variant 类型,不定类型参数,可以接受任何类型的参数,行、列、单元格自然不例外,因为它们肯定有归属类型。在Excle中,行、列、单元格本身不是类型,但都是Range类型的一个对象,所以归属Range类型。所以当把一个行或一个列作为参数传递给Sort时,实际上是被作为Range类传递的。
- Excle有很多预定义枚举类型,例如XLSortOrder、XlYesNoGuess、XlSortOrientation,还有很多预定义常量,例如xlDescending、xlAscending。我还没有找到在VFP里直接使用类型和常量的方法,现在只好在帮助文件查出数字,直接用数字作参数。等以后找到办法了再来补充调整这篇博客。
- OrderCustom,Variant 类型。这个参数很有作用,用来指明排序方式,是我这篇东西的核心,帮助文件里说明不够详细,要参考一下MSDN。
许多情况下我们并不希望按系统默认的方式排序,通过OrderCustom就可以指定其它排序方式。Excel以数值1代表系统默认排序方式,其它排序方式的代表值,是在1的基础上加上自定义排序方式在Excel自定义序列表中的序位合成。等一会儿再举例说明。
- 找到在指定排序方式,接下来就会想到怎么添加自定义序列。这个在Application的定义里,有这么几个方法属性:
- Sub AddCustomList( ListArray, [ByRow] ),增加一个自定义序列。按照帮助文件里的说法,ListArray也是一个不定类型参数,可以是一个数组,也可以是一个Range类。
- Sub DeleteCustomList( ListNum As Long ),删除自定义序列表中、序号是ListNum的序列。Excel退出时不会自动删除自定义序列,为了避免干扰其它程序,我们主动打扫战场。
- Function GetCustomListNum( ListArray ) As Long,返回字符串数组在自定义序列列表中的序号。这里的ListArray只能是字符串数组。
现在估计齐了,可以动手排序了。
设想我们要解决这样一个问题,对序列1月、2月、3月、4月、5月、6月、7月、8月、9月、10月、11月、12月排序,VFP达不到我们预期的效果,它会把10月、11月、12月排在1月的前面,按文字排,而不是按数字排。
因此我们用自定义序列解决。
eole = Createobject( 'excel.application' ) &&建立Excel对象。
dimension arrMonthlyOrderList[ 12 ] &&准备自定义的序列。
FOR i = 1 TO 12
arrMonthlyOrderList[ i ] = ALLTRIM( STR( i )) + '月' &&生成自定义序列。
ENDFOReole.AddCustomList( @arrMonthlyOrderList, ) &&把自定义序列加入Excel自定义月度序列表。
** 自定义序列在定义之前可能就已经存在,所以加入之前最好校验一下,以免打扫战场的时候清除多了。
** 但帮助文件里说如果对应序列不存在,getCustomListNum将出错,却又没有说出什么错。
** MSDN里没查到对应序列不能存在时getCustomListNum会有什么反应。
** 自己测试出来的getCustomListNum反应也不见得靠得住。
** 所以干脆省略了这一环。大家根据自己的情况酌情处理吧。
** 要求按自定义序列排序时,需指定排序方式。
** Excel以数值1代表系统默认排序方式。
** 其它排序方式的代码值,是在1的基础上加上自定义序列在Excel自定义序列表中的序位合成。
** 自定义序列在定义之前可能已经存在,所以不能肯定加在了最后,一定要从自定义序列表中提取序位。
nListNum = eole.getCustomListNum( @arrMonthlyOrderList ) + 1ebook = eole.workbooks.Open( 'D:\Documents\myExcel.xls' )
loxlSheet =eole.activesheetloxlSheet.Range( "c1:n137" ).;
Sort( loxlSheet.Range( "c1:n1" ),1,; &&按升序排列。
,,,,,2,; &&无标题。
nListNum,; &&按自定义序列排序。
,2,; &&对行排序。
,,,)loxlSheet.columns.AutoFit &&按列自动填充。
*** 清除自定义序列。
*** 清除过程中剩余序列在自定义序列表中的序位可能发生变化,所以必须重新提取序号。
eole.deleteCustomList( eole.getCustomListNum( @arrMonthlyOrderList ) )
ebook.Save
ebook.Closeeole.Quit
Release eole
以上代码在VFP + Excel2003环境下调试通过,大功告成。
(行文如有暇错,欢迎指正!)