VFP控制Excel排序

 

很多朋友在试图用VFP控制Excel都有过无从着手困惑,不知道该去调用哪些过程、方法、函数。

其实进入Excel后,如果我们按Alt-F11,打开Excel自带的Visual Basic编辑器,然后按F2,在对象浏览器里,可以找到许多有用资源。如下图。 

接下来就好办了,不停地与帮助文件对照,查找属性、方法的详细说明。

题外话,我总觉得微软编程序不够厚道,类、类的属性、类的实例经常使用同一个名字,例如类Range、Sheets、WorkBooks,都与类Application的一个属性同名,而且这些属性又恰好都是这些同名类,把我搞得晕晕糊糊,熟了之后才反应过来,哦,原来是不同的东西。有人夸这是C++灵活性的体现,我是不太喜欢这种编码方法,也许高手能挥洒自如吧。

打住,回头看看Excel里与排序有关的类、方法和函数。

Range类里有这么两个方法Sort 和 SortSpecial,从字面上看估计和排序有关,进入帮助看看。

  1. 关于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自定义序列表中的序位合成。
      等一会儿再举例说明。

  2. 找到在指定排序方式,接下来就会想到怎么添加自定义序列。这个在Application的定义里,有这么几个方法属性:
    1. Sub AddCustomList( ListArray, [ByRow] ),增加一个自定义序列。按照帮助文件里的说法,ListArray也是一个不定类型参数,可以是一个数组,也可以是一个Range类。
    2. Sub DeleteCustomList( ListNum As Long ),删除自定义序列表中、序号是ListNum的序列。Excel退出时不会自动删除自定义序列,为了避免干扰其它程序,我们主动打扫战场。
    3. 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 )) + '月'           &&生成自定义序列。
ENDFOR

eole.AddCustomList( @arrMonthlyOrderList, )       &&把自定义序列加入Excel自定义月度序列表。
**  自定义序列在定义之前可能就已经存在,所以加入之前最好校验一下,以免打扫战场的时候清除多了。
**  但帮助文件里说如果对应序列不存在,getCustomListNum将出错,却又没有说出什么错。
**  MSDN里没查到对应序列不能存在时getCustomListNum会有什么反应。
**  自己测试出来的getCustomListNum反应也不见得靠得住。
**  所以干脆省略了这一环。大家根据自己的情况酌情处理吧。


** 要求按自定义序列排序时,需指定排序方式。
** Excel以数值1代表系统默认排序方式。
** 其它排序方式的代码值,是在1的基础上加上自定义序列在Excel自定义序列表中的序位合成。
** 自定义序列在定义之前可能已经存在,所以不能肯定加在了最后,一定要从自定义序列表中提取序位。
nListNum  = eole.getCustomListNum( @arrMonthlyOrderList )  + 1   

ebook = eole.workbooks.Open( 'D:\Documents\myExcel.xls' )
loxlSheet =eole.activesheet

loxlSheet.Range( "c1:n137"  ).;
    Sort( loxlSheet.Range( "c1:n1" ),1,;          &&按升序排列。
   ,,,,,2,;                                                                &&无标题。
   nListNum,;                                                     &&按自定义序列排序。
   ,2,;                                                                    &&对行排序。
   ,,,)

loxlSheet.columns.AutoFit                             &&按列自动填充。


***  清除自定义序列。
***  清除过程中剩余序列在自定义序列表中的序位可能发生变化,所以必须重新提取序号。
eole.deleteCustomList( eole.getCustomListNum( @arrMonthlyOrderList ) )


ebook.Save
ebook.Close

eole.Quit
Release eole

 以上代码在VFP + Excel2003环境下调试通过,大功告成。

(行文如有暇错,欢迎指正!)

VFP实现选择排序 时间:2009-06-07来源:编程入门网 作者:老马   众所周知在常用的简单排序方法,前文所介绍的起泡排序(冒泡排序)是效率最差的一个了。我们今天所介绍的这个选择排序也是简单排序的一种,不过比起泡排序的效率要高,并且也比较容易实现。   这些常用的排序方法多见诸于C/C++方面的资料,如果要在vfp实现这些排序方法,原理是一样的,只是在代码实现上略有差别。例如,在C/C++数组的下标是从0开始,而vfp数组的下标是从1开始;C/C++的for语句可以采用for(i=0;i<n;i++)这种形式来同时完成变量赋初值、变量终值判断、变量递增这些操作,而vfp的for语句则有些弱,它的变量终值不能采取i<n这种形式来界定一个范围。因为以上的区别,在VFP书写代码时要特别注意数组下标问题及循环变量的初值及终值,在以后的文章不会再特别提及这些问题。   我们先看一下选择排序的基本思想和排序过程。(此部分内容引用自百度百科:http://baike.baidu.com/view/547263.htm)   基本思想   每一趟从待排序的数据元素选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。   选择排序是不稳定的排序方法。n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果:    ①初始状态:无序区为R[1..n],有序区为空。    ②第1趟排序   在无序区R[1..n]选出关键字最小的记录R[k],将它与无序区的第1个记录R[1]交换,使R[1..1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。   ……    ③第i趟排序   第i趟排序开始时,当前有序区和无序区分别为R[1..i-1]和R(1≤i≤n-1)。该趟排序从当前无序区选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使R[1..i]和R分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。   这样,n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果。   排序过程   【示例】:    初始关键字 [49 38 65 97 76 13 27 49]   第一趟排序后 13 [38 65 97 76 49 27 49]   第二趟排序后 13 27 [65 97 76 49 38 49]   第三趟排序后 13 27 38 [97 76 49 65 49]   第四趟排序后 13 27 38 49 [49 97 65 76]   第五趟排序后 13 27 38 49 49 [97 65 76]   第六趟排序后 13 27 38 49 49 65 [97 76]   第七趟排序后 13 27 38 49 49 76 [97 76]   最后排序结果 13 27 38 49 49 76 76 97   知道这个排序方法的基本思想和排序过程,在vfp书写代码就简单了,只是需要注意vfp数组的下标及循环变量的初值及终值与C/C++的区别。实例的运行界面如下图:   本例依然采取生成10个随机整数的方式取得数据,然后用选择法对这10个整数进行从小到大的排序。实现过程:   一、新建表单,向表单添加一个编辑框控件及三个命令按钮,按上图设置这三个命令按钮的caption属性。   二、添加代码:   1.“生成10个随机整数”按钮的click事件: public s(10) for i=1 to 10 s(i)=int(rand()*100) &&产生两位数的随机整数 thisform.edit1.value=thisform.edit1.value+str(s(i),5) endfor   2.“清屏”按钮的click事件:thisform.edit1.value=""   3.“选择排序”按钮的click事件: local i,j,k,t as integer for i=1 to 9 k=i for j=i+1 to 10 if s(j)<s(k) k=j endif endfor t=s(k) s(k)=s(i) s(i)=t endfor thisform.edit1.value="" for i=1 to 10 thisform.edit1.value=thisform.edit1.value+str(s(i),5) endfor
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值