VBA如何實現篩選條件之“排除某些值”

  小爬一般習慣使用Python來解決爬蟲和某些辦公自動化場景問題,不過最近卻需要實現一個VBA需求:從一堆人員處理的Excel數據記錄中,排除某些“用戶名稱”處理的數據。整個思考過程很有意思,很值得分享下。

這個需求看上去很簡單,實際當我們的待排除“用戶名稱”數超過2時,Excel原生的篩選“自定義篩選-不等於”功能是難以支持的:

 

 

 

   那麼這類問題該怎麼高效解決呢?

  小爬首先排除的方法是遍歷每一行的“用戶名稱”,然後進行remove等操作,因爲小爬的數據集超過50000行,這樣執着的遍歷方法顯然跟上文提到的“高效”不沾邊,自然不應該成爲我們自動化的首選方案;

  小爬緊接着試了下VBA的錄製宏功能:對數據進行篩選,然後手工勾選掉那些我們不想要的數據,再來看後臺VBE自動生成的代碼是否能稍加改造爲我所用,該場景裏,後臺的錄製的代碼長這樣:

Sub 宏1()

    Range("I1").Select
    Selection.AutoFilter
    ActiveSheet.Range("$A$1:$J$141").AutoFilter Field:=9, Criteria1:=Array("User1", "User11", "User12", "User13", "User14", "User15", "User16", "User17", "User18", "User19", "User2", "User20", "User3"), Operator:=xlFilterValues
End Sub

  可以看出,我們要排除的人員是User4到User10,但是錄製的宏代碼中,Array裏提到的人員恰恰是需要保留的人員數據(即篩選時勾選的人),這裏的“Operator:=xlFilterValues”指的是篩選後要保留哪些值,這裏的Field:=9 指的是我們要篩選的字段是表格的第9列。

那麼問題就轉化成了如下形式:

  如何得到某列所有的人員名單(去重重複項和空值),然後從這些名單中剔除掉我們的“排除人員名單”,從而得到我們最終的待保留人員名單,並存入一個array數組?

  下圖是我在ExcelHome論壇中看到的一個典型的方法:

 

   該方法可以快速將某一列值存入列表,然後藉助字典的鍵不重複這一特性來快速去重,最終將字典的鍵寫入新的列。該方法非常典型,不過當我們將某一列值快速存入數組(arr=[A1:A1000])時,默認得到的是二維數組(數組的二級下標默認爲1),同理,只有將某一行數據快速寫入數組,得到的纔是一維數組;

在這個“篩選中排除某些值”的場景,根據錄製宏的代碼,我們需要的應該是一個一維數組,內包含所有要篩選的結果。此時,我們可以利用excel的轉置功能快速將列變成行,達到快速將某列值存入一維數組的目的,有了思路,代碼就水到渠成了,下面是示例代碼:

Sub test()
'基於N列的排除人員名單,對“用戶名稱”列進行篩選,曬除這些人
Dim max_row As Integer
max_row = Sheets("Sheet1").Cells(Rows.Count, 9).End(xlUp).Row '得到表格第九列的最大行號
Set d = CreateObject("Scripting.Dictionary")
arr = Application.Transpose(Range("I2:I" & max_row).Value)
For i = LBound(arr) To UBound(arr) '將人員名單遍歷後,藉助字典,篩除重複值和空值
    If arr(i) <> "" Then d(arr(i)) = ""
Next
For i = 2 To 8 '將字典的鍵,去除人員名單,得到其他鍵,存入新的數組
    If d.Exists(Range("N" & i).Value) = True Then
        d.Remove (Range("N" & i).Value)
    End If
    
Next
newArr = d.keys '排除人員名單後的新數組
'For i = LBound(newArr) To UBound(newArr)
'Debug.Print (newArr(i))
'Next
Range("A1").Select
Selection.AutoFilter
Range("$A$1:$J$" & max_row).AutoFilter Field:=9, Criteria1:=newArr, Operator:=xlFilterValues '基於新的數組進行篩選(達到排除某些人員的效果)

End Sub

   通過上面的思路也可以看出來,簡單的一個“篩選——不包含某些值”的VBA場景,我們需要用到錄製宏功能,一維數組、二維數組功能、數組的轉置方法、字典的remove方法、字典鍵快速存入數組方法等。看上去每個單一功能都不復雜,但是任何一個功能掌握的不好,我們很可能就解決不了一個再常見不過的場景。工作中需要學會和總結的技能點還有很多,加油吧,騷年~

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章