excel - VBA字典没有为键赋值
问题描述
我创建了一个函数 getField,它查看电子表格的第二列和第三列,并返回一个字典,其中键是第二列,值是第三列。该函数接受一个字符串,该字符串是正在查找的字段名称,但现在我无法为键分配值。这是我指的是当前有效但值为空的行我尝试分配值失败所以我把它放在评论中向您展示我尝试过的所有内容。If InStr(data(r, 1), fieldName) > 0 Then dict(data(r, 1)) = Empty 'dict(value(r, 1))
这是其余的代码:
Public Function getField(fieldName As String)
Dim data(), dict As Object, r As Long
Set dict = CreateObject("Scripting.Dictionary")
data = ThisWorkbook.Worksheets("Sheet1").UsedRange.Columns(2).value
value = ThisWorkbook.Worksheets("Sheet1").UsedRange.Columns(3).value
For r = 1 To UBound(data)
If InStr(data(r, 1), fieldName) > 0 Then dict(data(r, 1)) = Empty 'dict(value(r, 1))
Next
data = WorksheetFunction.Transpose(dict.Keys())
Set getField = dict
End Function
解决方案
显示的代码表明您没有帮助自己。
有一个未声明的变量值。没有为函数声明返回类型。
因此,请在每个模块的开头插入 Option 显式,然后安装出色的 RubberDuck 插件并查看代码检查。这两个动作将为您在编写 VBA 宏时消除很多痛苦。
正如我在评论中提到的,代码不起作用的原因是因为这个结构。
dict(data(r, 1)) = dict(value(r, 1))
其中 dict(value(r,1)) 与 value(r,1) 作为字典值的键一起使用。这意味着第一次使用此构造时它将失败,因为字典中没有数据,因此 dict(value(r,1)) 试图访问不存在的数据。
正确的结构是
dict(data(r,1) = value(r,1)
其中要放入字典中的值 dict(data(r,1)) 是存储在索引 (r,1) 处的变量数组值中的值。
对于 scripting.dictionary 有两种添加数据的方法
Dict.add Key, Value
和
Dict(Key)=Value
如果字典中已经存在密钥,则上述第一个将失败。
第二种方法是一把双刃剑,如果字典中不存在该键,它将为该键创建一个条目,然后分配值。但是,如果密钥已经存在,它将覆盖分配给密钥的任何现有值。这可能是也可能不是所需的行为。
对于 add 方法,我们可以通过使用 'exists' 方法测试字典中键的存在来避免重复键发生错误。
If not dict.exists(key) then
dict.add key,value
Else
' what ever action is needed in the case of duplicate keys
End if
OP 提供的代码已更新并在下面显示。
Public Function getField(fieldName As String) as Scripting.Dictioanry
Dim myKeys As Variant 'Formerly data
myKeys = Excel.WorksheetFunction.Transpose(ThisWorkbook.Worksheets("Sheet1").UsedRange.Columns(2).Value)
Dim myItems As Variant 'Formerly value but not declared
myItems = Excel.WorksheetFunction.Transpose(ThisWorkbook.Worksheets("Sheet1").UsedRange.Columns(3).Value)
Dim myRow As Long
Dim myDict As Scripting.Dictionary
Set myDict = New Scripting.Dictionary
For myRow = 0 To UBound(myKeys)
If Not dict.Exists(myKeys(myRow)) Then
dict.Add myKeys(myRow), myItems(myRow)
Else
Debug.Print "Duplicate Key found: ", myKeys(myRow)
End If
Next
' No longer required
' data = WorksheetFunction.Transpose(dict.Keys())
Set getField = dict
End Function
如果我们有这样的情况,即使键重复,我们也想捕获所有值,那么我们只需创建一个字典字典
Public Function getField(fieldName As String) As Scripting.Dictioanry
Dim myKeys As Variant 'Formerly data
myKeys = Excel.WorksheetFunction.Transpose(ThisWorkbook.Worksheets("Sheet1").UsedRange.Columns(2).Value)
Dim myItems As Variant 'Formerly value but not declared
myItems = Excel.WorksheetFunction.Transpose(ThisWorkbook.Worksheets("Sheet1").UsedRange.Columns(3).Value)
Dim myRow As Long
Dim myDict As Scripting.Dictionary
Set myDict = New Scripting.Dictionary
For myRow = 0 To UBound(myKeys)
If Not dict.Exists(myKeys(myRow)) Then
' add a new dictionary as the value for the key
dict.Add myKeys(myRow), New Scripting.Dictionary
End If
' now add the value to the dictionary seleted by the key
' we just use the current size of the sub dictionary as the index (key)
' for the value
With dict.Item(myKeys(myRow))
.Add .Count, myItem(myRow)
End With
Next
Set getField = myDict
End Function
上面的代码创建了一个字典,其中分配给每个键的值本身就是一个字典。子字典收集具有相同键的所有值。您当然可以使用集合而不是子字典,因为这样就无需管理子字典的键。
要从字典中检索信息,您必须记住键检索字典
myValue = dict.item(key).item(index)
其中 Item 是用于访问字典值的默认成员(通常是隐藏的)例如上面可以写成,不太直观
myValue = myDict(key)(index)
推荐阅读
- reactjs - react-native keyboardDidShow/keyboardDidHide 键盘事件未触发
- multithreading - Julia中的多线程只有一个线程工作
- apache-spark - Spark:避免大量“代码生成”消息
- tensorflow - 如何关闭张量流 XLA?
- r - R 代码错误:请在脉冲中提供内生变量集中的变量名称
- angular - 除非刷新,否则在日期选择器中显示日期不显示
- c++ - 将信号量添加到 C++20 的基本原理是什么,而它被认为对 C++11 来说太危险了?
- java - 如何从 Spring Data JPA GROUP BY 查询返回对象列表而不是对象数组
- javascript - 将自定义对象返回给 GraphQL 解析器
- elastic-stack - logstash 向 elasticseach 集群发送数据的问题