自从学会了VBA字典,VLOOKUP都不那么香了
上篇博文中,小爬曾多次为VBA字典带货。鼓励多用字典,可以让我们的VBA脚本工具执行更快。今天小爬来细聊一下VBA字典的具体应用!如果你有一定VBA基础,那么看完你一定会对VBA字典有全新的认识;如果你还是这方面的新手,也不影响点赞收藏哈。
字典,其实就是一些“键-值”对。使用起来非常方便,有类似于微型数据库的作用,可用于临时保存一些数据信息。在很多其它编程语言里,我们也常称它为MAP。
我们先来简单看下字典如何创建,又具备哪些属性和方法。
一、字典的创建,用的是WSH引用
Dim mydic As Object
Set mydic = CreateObject("Scripting.Dictionary")
二 、字典有哪些方法可供调用
它有Add、Exists、Keys、Items、Remove、RemoveAll,六个方法。
① Add 用于添加内容到字典中。如mydic.Add key, item 第一个参数为键,第二个参数为键对应的值;
② Exists 用于判断指定的关键词是否存在于字典(的键)中。如mydic.Exists(key)。如果存在,返回True,否则返回False。通常会在向字典中添加条目的时候使用,即先判断字典中是否已存在这个记录,如果不存在则新增,否则进行其它的操作;
③ Keys 获取字典所有的键,返回类型是数组。如mydic.Keys();
④ Items 获取字典所有的值,返回类型是数组。如mydic.Items();
⑤ Remove 从字典中移除一个条目,是通过键来指定的。mydic.Remove(key)如果指定的键不存在,会发生错误;
⑥ RemoveAll 清空字典。
三、字典有哪些属性
它有Count、Key、Item、ConpareMode四种属性,其中前三个属性较为常用。
① Count 用于统计字典中键-值对的数量。也可以简单理解为统计字典中键的个数;
② Key 用于更改字典中已有的键。如:myd.Key("oapp") = "Orange" 如果指定的键不存在,则会产生错误;
③Item 用于写入或读取字典中指定键的值,如果指定的键不存在,则会新增。如.Item("oapp") = 10。
有了这些基础知识,我们就可以解决下面这些常见的业务问题了。
场景一:对表格某列值进行去重
下图所示内容通过python的faker库进行自动生成,非真实数据,感兴趣的童鞋,可以自行安装该faker库,生成自己想要的测试样表数据。

我们可以利用Exists方法判断某个名字是否已存在于字典,不存在则调用Add方法添加该名字为字典的key,至于value,我们该场景并不关心,可以随便存入"""空字符串。最后再通过遍历mydic.keys()(得到一个存有所有key的一维数组)的每一个元素,逐个输出到另一列,也可以选择覆盖原则,达到去除重复项的效果。也可以将数组一次性写入一个单元格区域(range的长度需要跟字典的长度一致,否则无法写入成功),代码示例如下:
1 Sub removeDuplicates()
2 Dim myDic As Object, i As Integer, sht As Worksheet, maxRow As Integer, totalCnt As Integer
3 Set myDic = CreateObject("scripting.dictionary")
4 Set sht = ThisWorkbook.Sheets("Sheet1")
5 maxRow = sht.Cells(Rows.Count, 1).End(xlUp).Row
6 For i = 2 To maxRow
7 If myDic.Exists(sht.Cells(i, 1).Value) = False Then
8 myDic.Add sht.Cells(i, 1).Value, ""
9 End If
10 Next
11
12 '方法一,利用transpose转置函数将一维数组转为一个N行一列的多维数组,找一个同样尺寸的range接收这个数组
13 totalCnt = myDic.Count
14 sht.Range("D2:D" & totalCnt) = Application.Transpose(myDic.Keys())
15
16 '方法二,用for each方法直接遍历一维数组的每个元素,依次存入特定单元格
17 i = 2
18 For Each Name In myDic.Keys
19 sht.Cells(i, 4).Value = Name
20 i = i + 1
21 Next
22 End Sub
场景二:模拟VLOOKUP(HLOOKUP同理)的精确匹配

假定此处,要根据Name来匹配Address,我们只需要先将姓名(key),地址(value,也就是Item)顺序存入字典,再根据Item方法读取某个Name对应的值。如果对应的Name在字典中没有找到,则address会返回空值,代码示例如下:
Sub myVlookup()
Dim myDic As Object, i As Integer, sht As Worksheet, maxRow As Integer, totalCnt As Integer
Application.ScreenUpdating = False
Set myDic = CreateObject("scripting.dictionary")
Set sht = ThisWorkbook.Sheets("Sheet1")
maxRow = sht.Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To maxRow
If myDic.Exists(sht.Cells(i, 1).Value) = False Then
myDic.Add sht.Cells(i, 1).Value, sht.Cells(i, 3).Value
End If
Next maxRow = sht.Cells(Rows.Count, 5).End(xlUp).Row '读取第五列的最后一行行号
For i = 2 To maxRow
sht.Cells(i, 6).Value = myDic.Item(sht.Cells(i, 5).Value) '根据第五列的key,将对应的item写入第六列
Next
Application.ScreenUpdating = True
End Sub
场景三:实现Vlookup不易实现的从右至左反向查找功能

假设很不凑巧,我们的【姓名】字段在【地址】字段后面,常规的Vlookup函数需要用到if还有数组 来实现,网上有很多相关资料,可惜公式对于新手而言,不是很容易理解,如果用字典来实现就太简单了,我们很容易在存入字典时调整列顺序,几乎没有多余的学习成本,代码如下:
Sub myReversalVlookup()
Dim myDic As Object, i As Integer, sht As Worksheet, maxRow As Integer, totalCnt As Integer
Application.ScreenUpdating = False
Set myDic = CreateObject("scripting.dictionary")
Set sht = ThisWorkbook.Sheets("Sheet1")
maxRow = sht.Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To maxRow
If myDic.Exists(sht.Cells(i, 3).Value) = False Then
myDic.Add sht.Cells(i, 3).Value, sht.Cells(i, 1).Value
End If
Next maxRow = sht.Cells(Rows.Count, 5).End(xlUp).Row '读取第五列的最后一行行号
For i = 2 To maxRow
sht.Cells(i, 6).Value = myDic.Item(sht.Cells(i, 5).Value) '根据第五列的key,将对应的item写入第六列
Next
Application.ScreenUpdating = True
End Sub
场景四:我们要根据【姓名】,匹配【地址】和【公司简称】

传统的方法,自然需要编写两个Vlookup公式,那么用字典来实现的话,同样传统的方法,我们需要两个字典(把它用两个字典分别查出地址和公司简称即可),这没啥难理解。如果我们要匹配的列数很多,则需要建立多个字典,难免语法上有些繁琐。如果想通过一个字典就实现查找多列的效果,你们想到偷懒的好法子了吗?
其实我们只需要将多列(value)加上特殊字符后拼接成一个value,最终取出来的时候,再基于这个特殊符号来split这个value,得到的数组每个元素其实就对应要查找的多列的值,此处小爬以同时查找地址和公司简称为例说明该trick。
示例代码如下:
Sub multiVlookup()
Dim myDic As Object, i As Integer, sht As Worksheet, maxRow As Integer, totalCnt As Integer, values As String
Application.ScreenUpdating = False
Set myDic = CreateObject("scripting.dictionary")
Set sht = ThisWorkbook.Sheets("Sheet1")
maxRow = sht.Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To maxRow
values = sht.Cells(i, 1).Value & "_" & sht.Cells(i, 2).Value '此处以"_"作为拼接字符,如果您觉得该字符可能出现在value中,可以换其它非常用字符来代替
If myDic.Exists(sht.Cells(i, 3).Value) = False Then
myDic.Add sht.Cells(i, 3).Value, values
End If
Next maxRow = sht.Cells(Rows.Count, 5).End(xlUp).Row '读取第五列的最后一行行号
For i = 2 To maxRow
values = myDic.Item(sht.Cells(i, 5).Value) '根据第五列的key,将对应的item写入第六列
sht.Cells(i, 6).Value = Split(values, "_")(0) '存入split分段后的数组的第一个元素,即为地址
sht.Cells(i, 7).Value = Split(values, "_")(1) '存入split分段后的数组的第二个元素,即为公司简称
Next
Application.ScreenUpdating = True
End Sub
场景五:匹配某个key最后一次出现的value

传统的vlookup精确匹配,我们总是匹配到第一个值,这个我们的场景二方案中已有使用字典的实现代码。比如此例中,假设姓名存在重名,我们要匹配最后一次出现的某个【姓名】对应的【公司简称】,使用vlookup将会很难实现,但是当我们有了字典,你会发现,原来可以这么简单干脆就解决我们以为的痛点,示例代码如下:
Sub mylookup()
Dim myDic As Object, i As Integer, sht As Worksheet, maxRow As Integer, totalCnt As Integer
Application.ScreenUpdating = False
Set myDic = CreateObject("scripting.dictionary")
Set sht = ThisWorkbook.Sheets("Sheet1")
maxRow = sht.Cells(Rows.Count, 1).End(xlUp).Row
'
For i = 2 To maxRow '不进行exists判断,那么如果某个key反复出现,则对应的value则会被后来值进行覆盖
myDic(sht.Cells(i, 1).Value) = sht.Cells(i, 3).Value '写入字典,如果有,则覆盖原来值
Next maxRow = sht.Cells(Rows.Count, 5).End(xlUp).Row '读取第五列的最后一行行号
For i = 2 To maxRow
sht.Cells(i, 6).Value = myDic.Item(sht.Cells(i, 5).Value)
Next
Application.ScreenUpdating = True
End Sub
其实利用vba字典来实现数据查找的案例远不止这些,小爬列举的五个场景,不过是其广阔应用的冰山一角。
希望通过对字典的功能和案例的介绍,能够对童鞋们今后的办公自动化工作有所启发,能够善用字典,在实际工作中真正用起来,感受它的魅力~~
快来扫码关注我的公众号 获取更多爬虫、数据分析的知识!

自从学会了VBA字典,VLOOKUP都不那么香了的更多相关文章
- 小学生都能学会的python(字典{ })
小学生都能学会的python(字典{ }) 1. 什么是字典 dict. 以{}表示. 每一项用逗号隔开, 内部元素用key:value的形式来保存数据 {"jj":"林 ...
- VBA字典
'字典并不存在于VBA中,需要调用 '调用方式1(前期绑定): '工具 --引用 - -浏览 - -找到scrrun.dll - 确定 '调用方式2 (后期绑定): ' Set d = CreateO ...
- Excel VBA ——字典实用技巧
最近写了一些小功能,对字典有了进一步的理解,太强大了! 个人最近用过的字典应用有这么几个,写下来防止自己忘~同时方便大家 一.查找重复行 [原理]利用字典的exist方法,将数据加入字典时判断一下,如 ...
- 使用VBA达到vlookup效果
Function Desc(ProdNum) Desc = Application.WorksheetFunction.VLookup(ProdNum, Range("myTable&quo ...
- VBA字典做数据有效性
Private Sub Worksheet_SelectionChange(ByVal Target As Range)If Target.Column = 26 And Range("f& ...
- 嫌Excel VBA执行速度慢,这些建议你一定要看
Excel是办公利器,这无需多言.尤其在办公室,Excel用的熟练与否,会的Excel知识点多不多,很大程度上决定了你工作是否高效,能否按时打卡下班.可我们也时常听到这样的吐槽:Excel好是好,可就 ...
- 在Excel VBA中使用SQL到底优势在哪儿
小爬在之前的博文中多次提到,可以在VBA中写SQL来操作Excel文件,实现各类数据处理和分析需求.那么,你可能有这样的疑问:Excel原生的VBA,数据透视表,数据分析功能不够吗,为啥一定要用SQL ...
- 我们都是IT民工---------流浪人IDE开发札记
你生命中的有些东西终究会失去,比如我住了6年的陈寨,这个聚集了郑州十几万IT民工的地方,说拆就拆了.再比如我玩了3年的坦克英雄,这个带给我太多快乐的游戏,说停就停了. 编程对我而言是种爱好,我上学6年 ...
- VBA笔记(三)——常用对象
VBA实际上就是操作Excel,把Excel进行拆解,划分多层对象,由顶至下为(也可以说是层层包裹): Application:代表Excel程序本性,之后我们操作对象都在它之下,因为是唯一且至高点, ...
随机推荐
- 文本处理的命令,三剑客之sed
文本处理的命令 1.sort命令 "用于将文件内容加以排序" 参数: -n :按照数值的大小排序 -r :以相反的顺序来排序 -k :以某列进行排序 -t :指定分隔符,默认是以空 ...
- mobx在react的使用
创建项目第六步 mobx 1.安装 yarn add mobx yarn add mobx-react 2.新建/src/store/store.js import {observable, co ...
- VUE3 之 样式绑定
1. 概述 老话说的好:脚踏实地,从小事做起. 言归正传,今天我们来聊聊 VUE3 的样式绑定. 2. 样式绑定 2.1 样式例子 <style> /* 颜色 */ .color-red ...
- 分享自己做的一个指定进程以及线程长时间cpu监控的工具
前言: 前面给大家分享过一个工作中用到的编译拷贝脚本,其实工作中还有一些其他工具的使用,今天再来分享一个自己纯手工的CPU监控的脚本.大家可以结合上篇文章与本篇文章一起学习shell. 主要实现功能: ...
- JAVAWEB进行PC支付宝支付、查询订单支付状态
官方文档:https://opendocs.alipay.com/open/270/105899 本地开发环境支付回调调试方法可以参考:https://www.cnblogs.com/pxblog/p ...
- Kafka Eagle分布式模式
1.概述 最近有同学留言,Kafka Eagle的分布式模式功能怎么使用,如何部署安装?今天笔者就为大家来详细介绍一下Kafka Eagle的分布式模式功能的安装和使用. 2.内容 首先,这里我们需要 ...
- 「算法笔记」FHQ-Treap
右转→https://www.cnblogs.com/mytqwqq/p/15057231.html 下面放个板子 (禁止莱莱白嫖板子) P3369 [模板]普通平衡树 #include<bit ...
- Loss Landscape Sightseeing with Multi-Point Optimization
目录 概 主要内容 代码 Skorokhodov I, Burtsev M. Loss Landscape Sightseeing with Multi-Point Optimization.[J]. ...
- 应用TYPE-C外围电源管理IC IM2605
应用于TYPE-C外围集成同步4开关Buck-Boost变换器的电源管理IC IM2605 IM2605描述 IM2605集成了一个同步4开关Buck-Boost变换器,在输入电压小于或大于输出电 ...
- Vue.js高效前端开发 • 【Ant Design of Vue框架进阶】
全部章节 >>>> 文章目录 一.栅格组件 1.栅格组件介绍 2.栅格组件使用 3.实践练习 二.输入组件 1.输入框组件使用 2.选择器组件使用 3.单选框组件使用 4.实践 ...