VBA调用外部对象01:字典Dictionary

2020-07-28 10:30:42 浏览数 (1)

当你发现不停的用For循环来处理数据速度慢的受不了了,你肯定会想怎么才能提高一些效率。比如前面我们说到的对比2个表数据,我们是使用For循环去逐个的对比判断,如果能有1个东西让我们可以快速的在一组数据里找到需要的、或者是找不到的时候返回false的话,那我们就不需要用For循环了,那有没有这种东西呢?

是的,今天要说到的字典就是这么一个东西,作为1个新手,可能你只需要知道它有快速找到某个数据的功能就可以了。如果你还有兴趣深入了解,那就需要去学习数据结构和算法方面的东西了,字典就是一种Hash算法实现的东西。

1、COM对象

字典就是Windows系统做好了的一个东西,是一种叫做COM对象的东西,在VBA中如果要使用的话,有2种方法:

  • 前期绑定:

在VBA编辑器里点击工具-引用,找到需要使用的项目勾选

  • 后期绑定:

使用VBA的CreateObject函数,这种情况下要知道COM对象的名称。

代码语言:javascript复制
VBA.CreateObject("XXXXX")

这样就可以在VBA里使用该对象了,2种方法有一点小的差异,主要是:

  • 前期绑定的方法使用对象时就像是使用VBA内部对象一样了,但是一旦你把做好的程序发给别人使用,使用者也必须要手动先添加引用
  • 后期绑定不需要手动添加引用,但是使用过程中不大方便,不能直接声明对象的名称,要用Object代替,写代码也不会像VBA内部对象那样自动列出属性和方法。

作为VBA的使用者,知道这样使用COM就可以了。

2、字典Dictionary

字典就是一种COM对象,前期绑定使用方法,找到Microsoft Scripting Runtime,勾选后确定,然后我们就可以使用字典了:

代码语言:javascript复制
Sub TestDic()
    '声明
    Dim d As Dictionary
    '创建
    Set d = New Dictionary
    '释放
    Set d = Nothing
End Sub

那我们如何能知道COM对象有些什么方法呢?还记得F2打开的对象浏览器吧,一旦我们引用了这个COM对象,在对象浏览器里我们就可以查看它了。

我们可以看到,其实这个库里面不止字典一个对象,还有些其他的,我们这次只看字典,可以看到他的方法有6个(绿色图标),属性有4个(灰色图标,蓝色那个是特殊的缺省属性,就像Range的Value属性,意思就是不写属性名的时候,默认就是它),总共10个东西,看起来还是挺简单的。

字典的方法、属性简单介绍:

  • 我们前面说了,字典最大的功能就是能够快速的查找到需要的东西,从里面的名称你应该能猜到,Exists就是判断某个东西是否存在于字典里面。
  • 而在判断是否存在之前,显然,我们需要先把数据装进去,很明显Add就是把数据装进去的方法。
  • 有添加自然也就会有删除,Remove就是删除某个数据,而RemoveAll显然就删除全部了,相当于把字典初始化了。
  • Count:很好理解,字典里存在多少个数据。
  • CompareMode:是设置文本的对比方式的,主要就是是否区分大小写。
  • Key、Keys:我们可以这样理解,字典,它真的很像我们使用的字典,比如汉字的新华字典,它的功能也是让我们快速查到需要的字,汉字的新华字典有一个可能我们没有在意过的特点,字在字典里是唯一的(多音字那些也是不同的字),也就是我们这个COM字典的重要特点,Key是唯一的,Add添加的就是这个Key,字典内部是不会有重复的Key的。Keys显然就是字典里的所有Key的集合,也就是一个数组了。
  • Item、Imtes:汉字的新华字典每一个字,都对应了一种对这个字的解释说明,这个解释说明显然是可能重复的。字典在添加Key的时候,同时也要指定这个Key所对应的Item。Items也就是Item的集合。

3、使用

代码语言:javascript复制
Sub TestDic()
    '声明
    Dim d As Dictionary
    '创建
    Set d = New Dictionary
    
    Dim arrA() As Variant
    Dim arrC() As Variant
    
    Dim rowA As Long
    Dim rowC As Long
    Dim i As Long, j As Long
    
    '获取A列和C列的最后一行行号
    rowA = Cells(Cells.Rows.Count, 1).End(xlUp).Row
    rowC = Cells(Cells.Rows.Count, 3).End(xlUp).Row
    
    '将A列和C列的数据存放到数组中
    arrA = Range("A1").Resize(rowA, 1).Value
    arrC = Range("C1").Resize(rowC, 1).Value
    
    '将A列数据记录到字典中
    For i = 2 To rowA
        d.Add arrA(i, 1), i
    Next
    
    '声明存储结果的数组
    Dim result() As Variant
    '数组使用一定要明确定义大小,结果数组肯定不会超过C列的数据数量
    ReDim result(1 To rowC, 1 To 1) As Variant
    
    '记录标题
    result(1, 1) = arrC(1, 1)
    
    '记录结果数据的个数
    Dim resultCount As Long
    resultCount = 1 '标题占用1个
    
    '用循环找出列C中不在列A中出现的数据
    '数据是从第2行开始的
    For i = 2 To rowC
        '判断C列的数据在字典中是否出现了
        '存在的情况Exists返回True,我们需要的不存在的,所以前面要加Not
        If Not d.Exists(arrC(i, 1)) Then
            '说明是在A列没有出现的数据,记录下来
            resultCount = resultCount   1 '结果的数量增加1
            result(resultCount, 1) = arrC(i, 1)
        End If
    Next
    
    '输出结果
    Range("E1").Resize(resultCount, 1).Value = result
    
    '释放
    Set d = Nothing
End Sub

有了字典,我们就不需要循环内部再加循环的去判断了,你可以多加些数据对比程序运行的速度,一定会很惊奇字典查找数据的速度。

最后推荐大家看一下这个帖子:

呼之即来,挥之即去:

http://club.excelhome.net/forum.php?mod=viewthread&tid=926188&ordertype=1&page=1

vba

0 人点赞