標籤:

在VBA中編寫排序代碼--Sort方法

在VBA中編寫排序代碼--Sort方法

看看下面的Excel界面截圖,「排序」和「篩選」往往在一起,這大概是很多數據需要先排序後篩選吧!

在Excel 2007中新增了Sort對象,在錄製宏時Excel會自動用到這個對象,但我們今天不會講解這個對象,待以後再詳解。今天主要講解Range對象的Sort方法,對於3個以內的欄位排序很方便。其語法如下:

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 所有參數均可選。

l 參數Key1、Key2、Key3指定排序欄位,確定要排序的值,但參數Key2、Key3不能用於排序數據透視表。

l 參數Order1、Order2、Order3,分別確定參數Key1、Key2、Key3指定值的排序順序,相應的常量值是xlDescending或者xlAscending(默認)。

l 參數Type,指定要排序的元素。僅用於數據透視表,可以指定為xlSortLabels或者xlSortValues。

l 參數Header,指定是否第一行包含標題信息,默認為xlNo。如果想要Excel嘗試確定標題,那麼指定其值為xlGuess。

l 參數OrderCustom,指定一個基於1的整數偏移量到自定義排序順序列表,使用自定義的排序順序進行排序。

l 參數MatchCase,設置為True執行區分大小寫的排序,為False則執行不區分大小寫的排序,不能用於數據透視表。

l 參數Orientation,默認按行進行排序且數據是垂直排列。如果數據是水平排列的,通過指定該參數使其按列進行排序。相應的常量值是xlSortRows或者xlSortColumn。

l 參數SortMethod,指定排序方法,適用於除英語以外的語言。

l 參數DataOption,有3個參數,用來指定排序時對單元格中文本和數字的處理。如果指定其值為xlSortTextAsNumbers,將文本當作數據進行排序,默認值是xlSortNormal,分別對數字和文本數據排序。不能應用於數據透視表排序。

參數DataOption1用於指定如何排序在Key1中指定的單元格區域中的文本。

參數DataOption2,用於指定如何排序在Key2中指定的單元格區域中的文本。

參數DataOption3,用於指定如何排序在Key3中指定的單元格區域中的文本。

下面以下圖所示的工作表來演示,以理解Sort方法及其參數。主要是介紹前面幾個參數,其它的參數將會在以後的文章中涉及時再進行相應講解。

首先以「性別」作為排序欄位,升序排列,並且第一行作為標題信息,代碼如下:

Sub testSort1()

Dim rng As Range

設置要排序的區域

Set rng = Range("A1:G10")

排序

rng.Sort Key1:="性別",Order1:=xlAscending, Header:=xlYes

End Sub

運行代碼後的結果如下圖:

接下來,再添加排序欄位:以「性別」作為第1排序欄位升序排列,以「總分」作為第2排序欄位降序排列。代碼如下:

Sub testSort2()

Dim rng As Range

設置要排序的區域

Set rng = Range("A1:G10")

排序

rng.Sort Key1:="性別",Order1:=xlAscending, _

Key2:="總分",Order2:=xlDescending, _

Header:=xlYes

End Sub

Excel將會以「性別」作為主要關鍵字升序排列,以「總分」作為次要關鍵字降序排列,即主關鍵字排序相同的,再以次關鍵字排序。結果如下圖所示:

示例1:查找滿足某項條件的所有數據並按順序排列

仍以上面的工作表為例,我們需要所有男同學的成績並以總分從高到低的順序排列。將排序與自動篩選結合,可達到我們的目的。

代碼如下:

Sub testSort3()

Dim rng As Range

設置要排序的區域

Set rng = Range("A1:G10")

排序

rng.Sort Key1:="性別",Order1:=xlAscending, _

Key2:="總分", Order2:=xlDescending,_

Header:=xlYes

篩選

rng.AutoFilter Field:=3, Criteria1:="男"

End Sub

運行代碼後的效果如下圖:

示例2:查找滿足某項條件的不重複數據

如本文開頭所示的工作表,要求獲取男女同學中總分最高的同學數據記錄。將排序與高級篩選相結合,可以達到我們的目的。

Sub testSort4()

Dim rng As Range

設置要排序的區域

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)

表示單元格區域rng中的第3列,即「性別」欄位列。

運行代碼後的效果如下圖:

示例3:雙擊列標題自動排序

在本文的示例工作表中,雙擊列標題,會升序排列該標題下的內容,再次雙擊該列標題,降序排列。代碼如下:

聲明變數,用於存儲升序降序值及排序列號

Dim iDirection As Integer

Dim iColumn As Integer

Private SubWorksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)

Dim rng As Range

設置排序的單元格區域

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事件中,在工作表單元格中雙擊滑鼠時發生該事件。(關於工作表事件,將在本系列文章後面的Worksheet對象系列中詳細講解)

l 在模塊頂部子過程外面聲明變數,表明該變數可用於該模塊下所有的子過程。本程序代碼之所以在模塊頂部聲明變數,是為了保存雙擊事件發生前變數的值,以便與雙擊事件發生後相關值比較,從而實現升序和降序的切換。(關於變數作用範圍,將在本系列文章後面詳細講解)

l Range("A1").CurrentRegion獲取單元格A1所在的區域,可參閱《ExcelVBA解讀(38):快速確定自已的地盤——CurrentRegion屬性》。

示例4:根據活動單元格排序

在上文所示的工作表中,當單元格在A1:G10區域內移動時,將根據活動單元格所處的位置對其所在列按降序排序。代碼如下:

Private SubWorksheet_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事件中,當活動單元格發生變化時觸發該事件。(關於工作表事件,將在本系列文章後面的Worksheet對象系列中詳細講解)

示例5:根據顏色排序

這是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中的數據排序

Range("C1") = "索引值"

Columns("A:C").SortKey1:=Range("C1"), _

Order1:=xlAscending, Header:=xlYes

清除列C中用於排序的臨時值

Columns(3).ClearContents

End Sub

說明

l 代碼中,首先使用ColorIndex屬性獲取列A中單元格顏色索引值,並將這些值存儲在列C中的相應行,然後對列C排序,從而達到對列A按顏色排序的效果。

l ClearContents方法用於清除單元格中的內容。

l 代碼運行的過程及結果如下圖所示:

示例6:排序有部分相同數據的行

如下圖所示,課程的組合有3種,分別是「語文、數學、英語」,「數學、體育、歷史」,「體育、化學、生物」,但上課的時間不同,要求將相同組合的課程排在一起。

代碼如下:

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

設置排序數據區域並按課程組合排序

Set rng = rng.Resize(, 5)

rng.Sort Key1:=rng.Columns(5),Order1:=xlDescending, Header:=xlYes

清除輔助列內容

rng.Columns(5).ClearContents

End Sub

說明

l 技巧:將多列組合成一列,並將該列作為排序列,從而達到相同數據排序在一起的目的。

示例7:自定義排序

如下圖所示,我們想按單元格區域I1:I5中的順序對單元格區域A1:G10進行排序。也就是說,無論數據如何變化,在單元格區域I1:I5中的5名同學都是按照這樣的順序排列。

代碼如下:

Sub CustomSort()

Dim iListNum As Integer

添加自定義列表

Application.AddCustomListListArray:=Range("I1:I5")

獲取列表編號

iListNum =Application.GetCustomListNum(Range("I1:I5").Value)

使用自定義列表排序

注意,應使用iListNum+1作為參數OrderCustom的值

『指定自定義列表(參見OrderCustom參數說明)

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方法。與排序相匹配使用的。(註:也與自動填充相匹配)

l AddCustomList方法的語法如下:

Application對象.AddCustomList(ListArray,ByRow)

添加自定義列表,用於自定義自動填充或自定義排序。其中,參數ListArray必需,指定自定義排序數據,可以是字元串數組或者Range對象。參數ByRow可選,僅用於當參數ListArray是Range對象時;設置為True時從單元格區域中的行創建自定義列表,設置為False時從單元格區域的列創建自定義列表;如果忽略該參數且單元格區域中的列比行多,那麼將從單元格區域行創建自定義列表。

注意,如果試圖添加的列表已存在,那麼該方法不會執行任何操作,會報出錯消息。

l GetCustomListNum方法的語法如下:

Application對象.GetCustomListNum(ListArray)

返回字元串數組的自定義列表編號,可以用於匹配內置列表和自定義列表。其中,參數ListArray必需,指定字元串數組。

注意,如果沒有相應的列表,那麼該方法將導致錯誤。

l DeleteCustomList方法的語法如下:

Application對象.DeleteCustomList(ListNum)

刪除自定義列表。其中,參數ListNum必需,指定自定義列表編號。編號必須大於或等於5,因為Excel有4個內置的不可刪除的自定義列表。

注意,如果列表編號小於5或者沒有相匹配的自定義列表,那麼該方法將導致錯誤。(這是Excel 2013幫助文檔中的說明,實際上Excel 2007中就有11個內置的不可刪除的列表。)

運行代碼後的結果如下圖:

本文首發於完美Excel微信號:excelperfect

原文名《ExcelVBA解讀(54):排序——Sort方法》,轉載請註明來源。

推薦閱讀:

PowerPoint怎樣用VBA?
Excel VBA 基礎(01.1)
快速匯總多個工作簿/工作表中的數據(Excel工具推薦)
Excel VBA入門(一)數據類型

TAG:VBA |