一種使用VBA對合併單元格排序的方法

在設計領域(不僅是程序設計)有一個常見的現象:越靈活的東西往往處理起來越複雜。Excel的合併單元格,就很明顯的體現了這一點。一方面我們使用合併單元格可以隨心所欲的設計出漂亮的表格(特別是老闆喜歡的那一種),但另一方面,當需要對這種表格進行統計、運算等等數據操作時,就會鬱悶甚至抓狂了。我們今天說的「對合併單元格進行排序」就是這樣一個典型的問題,因為即使Excel自帶的各種排序功能,對此也都束手無策。

這幾天我們在製作全民一起VBA實戰篇(Excel數據處理) - 網易雲課堂中的「數據處理專題」的過程中,發現很多網友都想了解對合併單元格排序的方法。網上當然可以搜索到一些案例和相關教程,比如下圖所示的這個例子(引自 excel-cn.com/tip/323-cn,感謝原作者的奉獻)。 但是這些案例大多使用了字典、數組等元素,導致代碼十分複雜(比如這個網路教程中給出的代碼長度大概在30行以上),不利於初學者理解。

圖1:合併單元格排序的案例,引自 excel-cn.com/tip/323-cn

圖2:excel-cn.com/tip/323-cn中提供的解決方案

顯然,上面的代碼對於初學者來說太過複雜,不便於學習和移植。所以我們針對同樣這個案例,設計了一個只有十幾行代碼的簡潔版解決方案,並在全民一起VBA實戰篇(Excel數據處理) - 網易雲課堂課程中專門錄製了一節課進行講解(專題二第八回)。考慮到這個方法可能對很多朋友都會有幫助,所以我們也把這個代碼發布到這篇文章中,以備朋友們需要時查閱。下面就是這種方法的VBA源代碼,並附有注釋。

圖3:程序運行效果(排序後)

這個解法仍然使用了我們在專題二第二回中介紹的「選擇排序法」思想,核心理念就是:做一個雙循環掃描表格,對記錄進行兩兩比較。比較的目標,就是每次都把剩餘記錄中數值最大的那一條,移動到這些記錄的最前面。這裡需要克服的兩點困難在於:(1)當一條記錄(比如一個公司)包含很多行的時候,怎樣能夠在下一次循環時直接跳到下一條記錄(公司)上,而不是簡單的下一行上(因為這一行有可能還是屬於當前公司合併單元格的一部分);(2)怎樣將一個包含合併單元格的數據區域整體移動到表格前面。

對於第一個問題,我們代碼中的辦法,是通過 Range.MergeArea 屬性獲取合併區域的行數來解決。而對於第二個問題,則是通過Range對象的剪切粘貼操作搞定。所以整個代碼的結構,其實與《實戰篇》前面學過的選擇法排序非常接近。

關於Range.MergeArea等合併單元格的處理知識和技巧,我們在《實戰篇》專題二的第七到八回中有詳細的講解和示例,包括怎樣利用它進行合併單元格統計計算、無損拆分等等特殊操作,大家在課程發布之後即可深入學習。

最後需要指明的是,使用字典和數組的解決方案雖然代碼更加複雜,但是在數據量很大的情況下,其程序運行速度會明顯高於剪切粘貼這種方式。所以大家在理解我們這個代碼之後,有時間時可以再研究一下網上的這種案例。

推薦閱讀:

怎樣做出乾淨漂亮的excel表格?
Word裡面如何在段落左邊添加豎線?
如何利用Office Online實現文檔在線預覽?
針對office辦公軟體初學者有什麼推薦書籍?
從中文字處理一哥,到微軟亦步亦趨的小弟,WPS到底經歷了什麼?

TAG:MicrosoftExcel | VBA | MicrosoftOffice |