大家好,今日我们继续讲解VBA数组与字典解决方案,今日讲解第68讲内容:利用字典和动态数组,找出多列数据中重复的值。
利用字典求多列间的重复数据,我们在工作时也会遇到类似的问题,对于这种问题的解决如果不用VBA往往是很难处理的,特别是多列间的重复数据,处理起来更麻烦,但利用了VBA往往会很快解决。
实例,如下数据,在ABC列中有很多的城市名称,要在其间找到三列均有的数据。如:北京市、唐山市、秦皇岛市。
思路分析:我们首先将数据装入数组,然后把A列数据装入字典,之后判断第二列的数据,如果在第一列数据中存在,如果存在,那么将数据装入第二个字典,之后再判断第三列的数据是否在第二个字典中存在,如果存在,那么就放到第三个字典中,最后在第三个字典中提取数据就可以了。下面看我给出的代码:
Sub mynzsz_68() '第68讲 利用字典和动态数组,找出多列数据中重复的值
Dim myarr, mybrr() '定义数组和动态数组
ReDim mybrr(0)
mybrr(0) = "三列均存在的数据"
Sheets("68").Select
'创建三个字典
Set myadic = CreateObject("scripting.dictionary")
Set mybdic = CreateObject("scripting.dictionary")
Set mycdic = CreateObject("scripting.dictionary")
'将源数据装入字典
myarr = Range("a2:c" & Range("a2").End(xlDown).Row)
'第一次计算A列数据装入字典
For x = 1 To UBound(myarr)
If myarr(x, 1) <> "" Then myadic(myarr(x, 1)) = ""
Next x
'第二次计算B列数据和A列数据重复的装入字典
For x = 1 To UBound(myarr)
If myarr(x, 2) <> "" And myadic.exists(myarr(x, 2)) Then
mybdic(myarr(x, 2)) = ""
End If
Next x
'第三次计算C列数据和AB列数据重复的装入字典
k = 0
For x = 1 To UBound(myarr)
If myarr(x, 3) <> "" And mybdic.exists(myarr(x, 3)) Then
k = k + 1
ReDim Preserve mybrr(k)
mybrr(k) = myarr(x, 3) '动态数组用于装C列中和AB重复的数据
mycdic(myarr(x, 3)) = "" '字典装不重复的数据
End If
Next x
'数据的回填
[f:g].ClearContents
[G1] = "三列均存在的不重复数据"
[f1].Resize(k + 1, 1) = Application.Transpose(mybrr)
[G2].Resize(mycdic.Count, 1) = Application.Transpose(mycdic.keys)
Set myadic = Nothing: Set mybdic = Nothing: Set mycdic = Nothing
End Sub
代码的截图:
代码解析:
1 上面代码首先将数据放到数组myarr中,同时建立三个字典,第一个字典myadic存放A列数据,第二个字典mybdic 存放第二列中与第一列相同的数据,第三个字典mycdic存放第三列数据中与第二个字典键数据相同的数据。最后在第三个字典中提取出所要的数据。
2 '第一次计算A列数据装入字典
For x = 1 To UBound(myarr)
If myarr(x, 1) <> "" Then myadic(myarr(x, 1)) = ""
Next x
上述代码将A列数据装入字典
3 '第二次计算B列数据和A列数据重复的装入字典
For x = 1 To UBound(myarr)
If myarr(x, 2) <> "" And myadic.exists(myarr(x, 2)) Then
mybdic(myarr(x, 2)) = ""
End If
Next x
上述代码将B列数据和第一个字典数据比较,有重复的数据放到第二个字典
3 '第三次计算C列数据和AB列数据重复的装入字典
k = 0
For x = 1 To UBound(myarr)
If myarr(x, 3) <> "" And mybdic.exists(myarr(x, 3)) Then
k = k + 1
ReDim Preserve mybrr(k)
mybrr(k) = myarr(x, 3) '动态数组用于装C列中和AB重复的数据
mycdic(myarr(x, 3)) = "" '字典装不重复的数据
End If
Next x
上述代码将C列数据和第二个字典数据比较,有重复的数据放到第三个字典
4 [G2].Resize(mycdic.Count, 1) = Application.Transpose(mycdic.keys)
上述代码在第三个字典中提取键,回填数据
5 Set myadic = Nothing: Set mybdic = Nothing: Set mycdic = Nothing
上述代码将三个字典清空释放内存
6 mybrr(k) = myarr(x, 3) '动态数组用于装C列中和AB重复的数据
上述代码利用动态数组mybrr(k)在第三列数据中提取和字典2重复的数据,但要注意这里面的数据是有重复值,没有排重,只有字典才有排重功能,所以代码中我用F列存放有重复的数据即这个动态数组mybrr;在G列存放没有重复的数据即字典mycdic的键。
下面看代码运行:
今日内容回向:
1 如何实现多列间重复数据的提取?
2 上面代码中动态数组和第三个字典的键的意义是否理解呢?