在 Excel VBA 中使用 Dictionary
需求 让 VBA 程序的配置数据放置在程序外面,使数据与逻辑分离
这样带来的好处就是可以通过修改配置而不需要修改代码来改变程序的行为。使 Excel VBA 程序的可维护性更好,让不会 VBA 程序的人也可以个性化程序的行为。
在 Excel VBA 中可以使用字典存储一些配置数据,参照机器人框架,让 Excel 程序也做到数据与逻辑分离。
Step 1 添加引用 Microsoft Scripting Runtime
要想使用 Excel VBA 的 Dictionary ,你必须先引用 Microsoft Scripting Runtime
Step 2 在程序中 New
一个 Dictionary 对象
Option Explicit
Public Sub DicTest()
'Step 2 Create a dictionary object
Dim dic As New Dictionary
End Sub
Step 3 像其它的编程语言( 如 C# )一样为字典添加键/值(Key / Value)对
Option Explicit
Public Sub DicTest()
'Step 2 Create a dictionary object
Dim dic As New Dictionary
'Step 3 Add key and value to the dictionary object
Call dic.Add("Key1", "this is the value of Key1")
End Sub
Step 4 你可以通过字典的 Item() 方法通过 Key 来获取对应的 Value
Option Explicit
Public Sub DicTest()
'Step 2 Create a dictionary object
Dim dic As New Dictionary
'Step 3 Add key and value to the dictionary object
Call dic.Add("Key1", "this is the value of Key1")
'Step 4 Using the method Item() to get the vaue by the key
Debug.Print dic.Item("Key1")
End Sub
毫无意外的,运行上述程序,在 Immediate 窗口中输出如下结果:
这着意味着我们可以像 REFFramework 一样,将所有的配置信息集中存储在一个 Config 文件中,在程序初始化阶段,将所有的配置数据读取到字典中,并在 Excel VBA 程序中传递这个字典,在需要的地方根据配置的 Key 来读取配置值。
哈哈,REFFramework 其实也可以指导我们更好地编写 VBA 程序。
其它
Q1:如果读取一个不存在的 key 会怎样?
A:程序并不会报错,会返回一个空的字符串
Q2: 如果添加了重复的 Key 会怎样?
A:会返回一个错误
Q3: 怎么避免 Add 重复 Key 的错误?
A:Add Key 之前先判断一下 Key 是否已经存在,如果存在,则不再添加或者覆盖,如果不存在则 Add 一个新的键值对。具体实现思路如下:
'Add the keys and values to the dic
With rngConfig
'# The settings should starts form row 2
For rowNum = 2 To .Rows.Count Step 1
'If the key is not empty, add it to the dictionay
If .Cells(rowNum, 1).Value <> "" Then
If dicConfig.Exists(.Cells(rowNum, 1).Value) Then
'If the key exits,overwrite the key
dicConfig.Item(.Cells(rowNum, 1).Value) = _
.Cells(rowNum, 2).Value
Else
'If the key not exits, add a new pair of key
Call dicConfig.Add(.Cells(rowNum, 1).Value, _
.Cells(rowNum, 2).Value)
End If
End If
Next rowNum
End With
Q4: 怎么遍历 dictionary ?
A:你不能通过 For each key in Dictionary.Keys
之类的语法来遍历 dictionary,因为你不能创建 key 对象,(Key 只是 Dictionary 的属性值,你没有什么办法可以创建它)
通过对象浏览器,你可以看到 dictionary 有一个 Count 属性表示 Keys 的总数,Keys 属性代表一个数组
对象浏览器我们可以尝试通过递增的索引一个个 key 读出来然后根据 key 用 item 方法把 Value 读出来,像这样:
Dim KeyIndex As Integer
For KeyIndex = 0 To (dicConfig.Count - 1) Step 1
Debug.Print dicConfig.Keys(KeyIndex) & "|" & _
dicConfig.Item(dicConfig.Keys(KeyIndex))
Next KeyIndex
注意: dictionary 对象的 Index 并不像 VBA 的数组那样以 1 开始,而是以 0 开始。
我的 config.xlsx 是这样的:
config.xlsx最终输出的结果如下:
一切都像我们预料的那样运行!
Q5: Dictionary 对象还有哪些属性和方法?
A: 其实你可以通过 VBE 自带的对象浏览器查看。Dictionary 对象的方法和属性其实不多,但是麻雀虽小,五脏俱全。它拥有字典对象应该有的一切。只要你使用得合理,字典得特性一样都不会少。