在以前的博客《使用字典快速获取唯一值与重复值(交集与并集)》使用多个字典对象获取交集与并集,最近有同学提问,是否可以只使用一个字典对象实现相同的功能,对于有“编程洁癖”的同学来说,可能不喜欢使用多个字典对象。
实例需求:表1和表2为两个名单,不同班级有同名的学生,例如表2中有两个小王(截图中黄色单元格),因此需要使用班级+姓名
作为学生的唯一识别标识,现在需要统计如下三个清单
- 表1有表2无
- 表1无表2有
- 两表共有
示例代码如下。
Sub demo()
Set objDic = CreateObject("scripting.dictionary")
arr = ActiveSheet.Range("a2").CurrentRegion
For i = 3 To UBound(arr)
sKey = arr(i, 2) & "|" & arr(i, 3)
objDic(sKey) = 1
Next
brr = ActiveSheet.Range("e2").CurrentRegion
For i = 3 To UBound(brr)
sKey = brr(i, 2) & "|" & brr(i, 3)
If objDic.Exists(sKey) Then
objDic(sKey) = 3
Else
objDic(sKey) = 2
End If
Next
range("I3:P31").clearcontents
iRow = 3: lRow = 3: oRow = 3
For Each strKey In objDic.Keys
If objDic(strKey) = 1 Then
ActiveSheet.Cells(iRow, "I").Resize(, 2) = Split(strKey, "|")
iRow = iRow + 1
ElseIf objDic(strKey) = 2 Then
ActiveSheet.Cells(lRow, "L").Resize(, 2) = Split(strKey, "|")
lRow = lRow + 1
ElseIf objDic(strKey) = 3 Then
ActiveSheet.Cells(oRow, "O").Resize(, 2) = Split(strKey, "|")
oRow = oRow + 1
End If
Next
Set objDic = Nothing
End Sub
【代码解析】
第1行代码创建字典对象。
第3行代码将表1读取到数组中。
第4~7行代码循环遍历表1中的数据。
第5行代码将班级和姓名组合作为字典对象的键,其中使用竖线作为分隔符,以便于回写数据时进行拆分。
第6行代码将键加入到字典中,其值设置为1。
第8~16行处理表2的数据,主要结构同上。
第11行代码判断键是否存在于字典中。
- 如果存在,说明是两表共用的数据,第12行代码将值修改为3。
- 如果不存在,说明是表2独有的数据,第14行代码将值修改为2。
至此,将全部数据加载到字典对象中,根据键值(1,2,3
)可以区分该学生属于哪个清单。
第17行代码清空结构单元格区域。
第18行代码设置3个清单的起始行为第3行。
第19~30行代码循环遍历字典对象中的键。
第20~29行代码根据键值,分别写入I、L或者O列相应的单元格中。
其中,resize(, 2)
将单元格区域扩展至一行两列,即两个单元格。
Split
函数将拆分班级和姓名,用于写入单元格区域。
第30行代码释放对象变量所占用的系统资源。
字典对象很灵活,充分利用其特性可以实现很多功能,希望本文对于各位同学有帮助。