VBA实践技巧精粹009:将工作表按指定顺序排序

问题提出:实际上自己感觉用处不是很大,非得需要将工作表进行排序吗?只要能访问不就可以吗?但既然提出来了,就看看吧,而且里面有个算法对我很有价值,就是排序算法,以前遇到需要排序的要求,心里就害怕,这次就借着这个问题,把它解决吧.

Sub 工作表按升序排序()
    Dim i As Integer, j As Integer, n As Integer
    Dim Sht() As String, t As String
    n = Sheets.Count
    ReDim Sht(1 To n) '注意数组定义的写法,可以直接实现从1开始啊.不用再在过程前写Option Base 1了.
    For i = 1 To n '将所有工作表名字逐一写入数组,为排序进行准备
        Sht(i) = Sheets(i).Name
    Next i
    For i = 1 To n - 1 '按从大到小排序,即降序排列,书中写错了.
        For j = i + 1 To n
            If Sht(i) < Sht(j) Then '如果前1个小于后1个,则将二者交换顺序,这样交换完后,大的在前,小的在后.
                t = Sht(i)          '先参与循环的为1到n-1,后参与循环的为后1个到n,这样就可以保证所有数据都参与排序.
                Sht(i) = Sht(j)
                Sht(j) = t
            End If
        Next j
    Next i
    For i = 1 To n 
        Debug.Print Sht(i)   '此时输出的结果即为从大到小
        Worksheets(Sht(i)).Move before:=Sheets(1) '先将最大的移到第1个工作表前,再将其次的移到最前面,这样循环下来,就可以实现将最小的移到最前面,恰好符合要求.
    Next i
End Sub

这种排序的方式是逐字符进行比较,纯字母的排序完全可以得到想要的结果,但如果工作表名称中含有字母+数字或者纯数字的话,恐怕得到的结果就不是自己要的.如下图所示:

明显的不是按数字大小排序,这也从另一方面说明上述比较方法是逐字符进行比较的,因为0的ASCII码为48在0-9中最小,所以......

如何改进呢?想办法变成按真正的数字大小进行排序,尤其是在工作名称是sheet1/sheet2/Sheet10/Sheet20......样式时.

Sub 工作表按升序排序的改进()
    Dim i As Integer, j As Integer, n As Integer
    Dim arr1() As Integer, arr2() As Integer
    n = Sheets.Count
    ReDim arr1(1 To n)
    ReDim arr2(1 To n)
    For i = 1 To n
        arr1(i) = Val(Mid(Sheets(i).Name, 6)) '将数字式的字符串转换成数值类型
    Next i
    For i = 1 To n
        arr2(i) = Application.WorksheetFunction.Large(arr1, i) '利用工作表中的Large函数获取第i大的数值到数组arr2中
        Debug.Print arr2(i)
    Next i
    For i = 1 To n
        Worksheets(Left(Worksheets(i).Name, 5) & arr2(i)).Move before:=Sheets(1) '考虑到sheet大小写不一样,尤其是s,故对工作表名称重新组合后排序.
    Next i
End Sub
最终效果如图所示:

注意sheet44与Sheet45的区别.

代码反思:两种方法都有价值,但用途不一样.第1种适用于字母的比较;第2种适用于字母加数字的比较,而且是有规律的比较.

了解了如果更改大小写呢?Ucase和Lcase函数可以实现,这是VBA中的函数.


 

菊子曰 今天你菊子曰了么?
posted @ 2011-04-14 09:15  surfacetension  阅读(2406)  评论(0编辑  收藏  举报