标签:VBA,AdvancedFilter方法
在处理大型数据集时,很可能需要查找并获取唯一值,特别是唯一字符串。例如,在一个有100000条记录的数据集中,其中可能包含数百个唯一字符串,如果将这些唯一记录提取出来,那么数据清理会变得更容易。
在VBA中,AdvancedFilter方法是处理这种情形的非常强大的一个工具。该方法可以保留原数据,采用基于工作表的条件,可以找到唯一值。下面,将详细介绍如何获取并将唯一值放置在单独的地方。
设置要筛选的单元格区域
AdvancedFilter方法对Range对象进行操作。接通常做法,设置单元格区域,但要注意,VBA始终将第一行视为包含标题的行。如果数据没有标题,即第一个单元格是常规值,则第一个值可能会在唯一值列表中出现两次。
通常,我们只是在一列中查找唯一值。例如,如果在列B中查找唯一值,则代码如下:
代码语言:javascript复制Range("B:B").AdvancedFilter
或者:
代码语言:javascript复制Columns(3).AdvancedFilter
注意,单元格区域可以是Columns集合中的单个列,也可以是Range对象。AdvancedFilter方法可以对多个列进行操作,如果只想筛选数据的子集,则可以限制其行范围。
可以跨列筛选唯一值。例如,如果A列包含设备名称,B列包含设备安装地点,使用Range(“A:B”).AdvancedFilter方法可查找唯一的“名称 地点”组合。这可以扩展到任意数量的列。
筛选结果输出到同一位置或新的位置
AdvancedFilter可以将筛选结果就放置在原数据位置(隐藏与条件不匹配的记录),也可以将结果输出到新位置。建议将筛选结果放置到新位置,这是保持原始数据完整性的好方法。
参数Action
参数Action告诉AdvancedFilter将输出结果放置在原始数据位置(设置值为xlFilterInPlace),还是放置在新位置(设置值为xlFilterCopy)。
参数CopyToRange
如果选择xlFilterCopy作为参数Action的值,则需要指定要放置副本的位置。CopyToRange参数执行此操作,可以只指定一个单元格,也可以指定整个列。如果输出区域太小,无法包含所有结果,VBA将溢出该区域。这意味着无法限制输出,因此要选择一个没有值或可以覆盖原有值的列。
另一个需要注意的是,如果要筛选的数据中有两列具有相同的标题,xlFilterCopy可能会将具有该名称的第一列复制两次到目标列(CopyToRange)。
查找唯一值
最后是布尔参数Unique,它只接受TRUE或FALSE。若要查找唯一值,将其设置为TRUE。
如下图1所示,要查找数据集中唯一位置值,并将结果放置到列E,可以使用代码:
Range("C:C").AdvancedFilterxlFilterCopy, , Range("E1:E1"), True
不要忘了空的CriteriaRange参数。输出如下:
图1
要找到“名称 地点”组合的唯一值,使用代码:
代码语言:javascript复制Range("A:B").AdvancedFilterxlFilterCopy, , Range("G1:G1"), True
输出如下:
图2
可以通过计算AdvancedFilter方法的输入和输出来检查原始数据是否有重复项。如果值的数量相匹配,则原始数据没有任何重复项。方法之一是使用WorksheetFunction.Count方法。
下面的代码给出是否列A中的数据有重复值:
代码语言:javascript复制Sub OriginalIfUnique()
Dim iBeforeCount As Integer
Dim iAfterCount As Integer
Range("A:A").AdvancedFilter xlFilterCopy, ,Range("J:J"), True
iBeforeCount = WorksheetFunction.CountA(Range("A:A"))
iAfterCount = WorksheetFunction.CountA(Range("J:J"))
If iBeforeCount = iAfterCount Then MsgBox ("原数据都是唯一值")
If iBeforeCount <> iAfterCount Then MsgBox ("原数据有重复值")
End Sub
小结
本文展示了如何在单列或连续列中筛选出唯一的记录,如何将结果放在一个单独的位置供以后比较。一旦有了唯一的记录,就可以使用自动筛选对其进行排序和进一步筛选。