看看下面的Excel界面截圖,“排序”和“篩選”往往在一起,這大概是很多數(shù)據(jù)需要先排序后篩選吧!

在Excel 2007中新增了Sort對象,在錄制宏時Excel會自動用到這個對象,但我們今天不會講解這個對象,待以后再詳解。今天主要講解Range對象的Sort方法,對于3個以內(nèi)的字段排序很方便。其語法如下:
Range對象.Sort(Key1,Order1 As XlSortOrder, _
Key2,Type,Order2As XlSortOrder, _
Key3,Order3As XlSortOrder, _
HeaderAs XlYesNoGuess, _
OrderCustom,MatchCase,_
OrientationAs XlSortOrientation, _
SortMethodAs XlSortMethod, _
DataOption1As XlSortDataOption, _
DataOption2As XlSortDataOption, _
DataOption3As XlSortDataOption)
說明:
l所有參數(shù)均可選。
l參數(shù)Key1、Key2、Key3指定排序字段,確定要排序的值,但參數(shù)Key2、Key3不能用于排序數(shù)據(jù)透視表。
l參數(shù)Order1、Order2、Order3,分別確定參數(shù)Key1、Key2、Key3指定值的排序順序,相應的常量值是xlDescending或者xlAscending(默認)。
l參數(shù)Type,指定要排序的元素。僅用于數(shù)據(jù)透視表,可以指定為xlSortLabels或者xlSortValues。
l參數(shù)Header,指定是否第一行包含標題信息,默認為xlNo。如果想要Excel嘗試確定標題,那么指定其值為xlGuess。
l參數(shù)OrderCustom,指定一個基于1的整數(shù)偏移量到自定義排序順序列表,使用自定義的排序順序進行排序。
l參數(shù)MatchCase,設置為True執(zhí)行區(qū)分大小寫的排序,為False則執(zhí)行不區(qū)分大小寫的排序,不能用于數(shù)據(jù)透視表。
l參數(shù)Orientation,默認按行進行排序且數(shù)據(jù)是垂直排列。如果數(shù)據(jù)是水平排列的,通過指定該參數(shù)使其按列進行排序。相應的常量值是xlSortRows或者xlSortColumn。
l參數(shù)SortMethod,指定排序方法,適用于除英語以外的語言。
l參數(shù)DataOption,有3個參數(shù),用來指定排序時對單元格中文本和數(shù)字的處理。如果指定其值為xlSortTextAsNumbers,將文本當作數(shù)據(jù)進行排序,默認值是xlSortNormal,分別對數(shù)字和文本數(shù)據(jù)排序。不能應用于數(shù)據(jù)透視表排序。
參數(shù)DataOption1用于指定如何排序在Key1中指定的單元格區(qū)域中的文本。
參數(shù)DataOption2,用于指定如何排序在Key2中指定的單元格區(qū)域中的文本。
參數(shù)DataOption3,用于指定如何排序在Key3中指定的單元格區(qū)域中的文本。
下面以下圖所示的工作表來演示,以理解Sort方法及其參數(shù)。主要是介紹前面幾個參數(shù),其它的參數(shù)將會在以后的文章中涉及時再進行相應講解。

首先以“性別”作為排序字段,升序排列,并且第一行作為標題信息,代碼如下:
Sub testSort1()
Dim rng As Range
'設置要排序的區(qū)域
Set rng = Range("A1:G10")
'排序
rng.Sort Key1:="性別",
Order1:=xlAscending, Header:=xlYes
End Sub
運行代碼后的結(jié)果如下圖:

接下來,再添加排序字段:以“性別”作為第1排序字段升序排列,以“總分”作為第2排序字段降序排列。代碼如下:
Sub testSort2()
Dim rng As Range
'設置要排序的區(qū)域
Set rng = Range("A1:G10")
'排序
rng.Sort Key1:="性別",
Order1:=xlAscending, _
Key2:="總分",
Order2:=xlDescending, _
Header:=xlYes
End Sub
Excel將會以“性別”作為主要關鍵字升序排列,以“總分”作為次要關鍵字降序排列,即主關鍵字排序相同的,再以次關鍵字排序。結(jié)果如下圖所示:

示例1:查找滿足某項條件的所有數(shù)據(jù)并按順序排列
仍以上面的工作表為例,我們需要所有男同學的成績并以總分從高到低的順序排列。將排序與自動篩選結(jié)合,可達到我們的目的。
代碼如下:
Sub testSort3()
Dim rng As Range
'設置要排序的區(qū)域
Set rng = Range("A1:G10")
'排序
rng.Sort Key1:="性別",
Order1:=xlAscending, _
Key2:="總分", Order2:=xlDescending,
_
Header:=xlYes
'篩選
rng.AutoFilter Field:=3, Criteria1:="男"
End Sub
運行代碼后的效果如下圖:

示例2:查找滿足某項條件的不重復數(shù)據(jù)
如本文開頭所示的工作表,要求獲取男女同學中總分最高的同學數(shù)據(jù)記錄。將排序與高級篩選相結(jié)合,可以達到我們的目的。
Sub testSort4()
Dim rng As Range
'設置要排序的區(qū)域
Set rng = Range("A1:G10")
'排序
rng.Sort Key1:="性別",
Order1:=xlAscending, _
Key2:="總分",
Order2:=xlDescending, _
Header:=xlYes
'篩選
rng.Columns(3).AdvancedFilterAction:=xlFilterInPlace, _
Unique:=True
End Sub
代碼中的:
rng.Columns(3)
表示單元格區(qū)域rng中的第3列,即“性別”字段列。
運行代碼后的效果如下圖:

示例3:雙擊列標題自動排序
在本文的示例工作表中,雙擊列標題,會升序排列該標題下的內(nèi)容,再次雙擊該列標題,降序排列。代碼如下:
'聲明變量,用于存儲升序降序值及排序列號
Dim iDirection As Integer
Dim iColumn As Integer
Private Sub
Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim rng As Range
'設置排序的單元格區(qū)域
Set rng =Range("A1").CurrentRegion
'限定在前8列第1行
If Target.Column < 8 And Target.Row = 1Then
If Target.Column <> iColumn Then
iColumn = Target.Column
'默認設置為升序排列
iDirection = xlAscending
Else
'在升序與降序之間切換
If iDirection = xlAscending Then
iDirection = xlDescending
Else
iDirection = xlAscending
End If
End If
'排序
rng.Sort Key1:=rng.Cells(1, iColumn), _
Order1:=iDirection, _
Header:=xlYes
End If
End Sub
說明:
l代碼位于工作表模塊的Worksheet_BeforeDoubleClick事件中,在工作表單元格中雙擊鼠標時發(fā)生該事件。(關于工作表事件,將在本系列文章后面的Worksheet對象系列中詳細講解)
l在模塊頂部子過程外面聲明變量,表明該變量可用于該模塊下所有的子過程。本程序代碼之所以在模塊頂部聲明變量,是為了保存雙擊事件發(fā)生前變量的值,以便與雙擊事件發(fā)生后相關值比較,從而實現(xiàn)升序和降序的切換。(關于變量作用范圍,將在本系列文章后面詳細講解)
lRange("A1").CurrentRegion獲取單元格A1所在的區(qū)域,可參閱《Excel
VBA解讀(38):快速確定自已的地盤——CurrentRegion屬性》。
示例4:根據(jù)活動單元格排序
在上文所示的工作表中,當單元格在A1:G10區(qū)域內(nèi)移動時,將根據(jù)活動單元格所處的位置對其所在列按降序排序。代碼如下:
Private Sub
Worksheet_SelectionChange(ByVal Target As Range)
Dim rng As Range
Set rng = Range("A1:G10")
'將范圍限定在列A至列G和1至10行
If Target.Column < 8 And Target.Row <11 Then
rng.Sort Key1:=ActiveCell,Order1:=xlDescending, Header:=xlYes
End If
End Sub
說明:
l代碼位于工作表模塊的Worksheet_SelectionChange事件中,當活動單元格發(fā)生變化時觸發(fā)該事件。(關于工作表事件,將在本系列文章后面的Worksheet對象系列中詳細講解)
示例5:根據(jù)顏色排序
這是Excel 2013 VBA幫助文檔中Sort方法的示例,按單元格的背景色進行排序。示例代碼如下:
Sub SortbyColor()
Dim lngLastRow As Long
Dim i As Long
'列A中最后一個單元格
lngLastRow = Range("A" &Rows.Count).End(xlUp).Row
'遍歷列A中的單元格并將其背景色索引值放置在列C中相應單元格
For i = 2 To lngLastRow
Cells(i, 3) = Cells(i,1).Interior.ColorIndex
Next i
'基于列C中的數(shù)據(jù)排序
Range("C1") = "索引值"
Columns("A:C").SortKey1:=Range("C1"), _
Order1:=xlAscending, Header:=xlYes
'清除列C中用于排序的臨時值
Columns(3).ClearContents
End Sub
說明:
l代碼中,首先使用ColorIndex屬性獲取列A中單元格顏色索引值,并將這些值存儲在列C中的相應行,然后對列C排序,從而達到對列A按顏色排序的效果。
lClearContents方法用于清除單元格中的內(nèi)容。
l代碼運行的過程及結(jié)果如下圖所示:

示例6:排序有部分相同數(shù)據(jù)的行
如下圖所示,課程的組合有3種,分別是“語文、數(shù)學、英語”,“數(shù)學、體育、歷史”,“體育、化學、生物”,但上課的時間不同,要求將相同組合的課程排在一起。

代碼如下:
Sub SortSameData()
Dim rng As Range
Dim str As String
Dim i As Long, j As Long
Set rng = Range("A1:D10")
'提取課程組合并放置在排序輔助列
For i = 2 To rng.Rows.Count
str = ""
For j = 2 To rng.Columns.Count
str = str & Cells(i, j)
Next j
Cells(i, j) = str
Next i
'設置排序數(shù)據(jù)區(qū)域并按課程組合排序
Set rng = rng.Resize(, 5)
rng.Sort Key1:=rng.Columns(5),Order1:=xlDescending, Header:=xlYes
'清除輔助列內(nèi)容
rng.Columns(5).ClearContents
End Sub
說明:
l技巧:將多列組合成一列,并將該列作為排序列,從而達到相同數(shù)據(jù)排序在一起的目的。
示例7:自定義排序
如下圖所示,我們想按單元格區(qū)域I1:I5中的順序?qū)卧駞^(qū)域A1:G10進行排序。也就是說,無論數(shù)據(jù)如何變化,在單元格區(qū)域I1:I5中的5名同學都是按照這樣的順序排列。

代碼如下:
Sub CustomSort()
Dim iListNum As Integer
'添加自定義列表
Application.AddCustomListListArray:=Range("I1:I5")
'獲取列表編號
iListNum =Application.GetCustomListNum(Range("I1:I5").Value)
'使用自定義列表排序
'注意,應使用iListNum+1作為參數(shù)OrderCustom的值
‘指定自定義列表(參見OrderCustom參數(shù)說明)
Range("A1:G10").Sort Key1:=Range("B1"),Order1:=xlAscending, _
Header:=xlYes,OrderCustom:=iListNum + 1
'移除自定義列表,以便于再次運行代碼
Application.DeleteCustomList iListNum
End Sub
說明:
l這段程序代碼中有3個我們以前沒有見過的方法,即Application對象的AddCustomList方法、GetCustomListNum方法、DeleteCustomList方法。與排序相匹配使用的。(注:也與自動填充相匹配)
lAddCustomList方法的語法如下:
Application對象.AddCustomList(ListArray,ByRow)
添加自定義列表,用于自定義自動填充或自定義排序。其中,參數(shù)ListArray必需,指定自定義排序數(shù)據(jù),可以是字符串數(shù)組或者Range對象。參數(shù)ByRow可選,僅用于當參數(shù)ListArray是Range對象時;設置為True時從單元格區(qū)域中的行創(chuàng)建自定義列表,設置為False時從單元格區(qū)域的列創(chuàng)建自定義列表;如果忽略該參數(shù)且單元格區(qū)域中的列比行多,那么將從單元格區(qū)域行創(chuàng)建自定義列表。
注意,如果試圖添加的列表已存在,那么該方法不會執(zhí)行任何操作,會報出錯消息。
lGetCustomListNum方法的語法如下:
Application對象.GetCustomListNum(ListArray)
返回字符串數(shù)組的自定義列表編號,可以用于匹配內(nèi)置列表和自定義列表。其中,參數(shù)ListArray必需,指定字符串數(shù)組。
注意,如果沒有相應的列表,那么該方法將導致錯誤。
lDeleteCustomList方法的語法如下:
Application對象.DeleteCustomList(ListNum)
刪除自定義列表。其中,參數(shù)ListNum必需,指定自定義列表編號。編號必須大于或等于5,因為Excel有4個內(nèi)置的不可刪除的自定義列表。
注意,如果列表編號小于5或者沒有相匹配的自定義列表,那么該方法將導致錯誤。(這是Excel 2013幫助文檔中的說明,實際上Excel 2007中就有11個內(nèi)置的不可刪除的列表。)
運行代碼后的結(jié)果如下圖:

本文首發(fā)于完美Excel公眾號:excelperfect
原標題為《Excel VBA解讀(54):排序——Sort方法》,轉(zhuǎn)載請注明來源。
歡迎分享與交流。