Excel VBA中的嵌套字典:错误457:此键已与集合的元素关联

Excel VBA中的嵌套字典:错误457:此键已与集合的元素关联,excel,vba,dictionary,Excel,Vba,Dictionary,我正在尝试用vba创建一个字典结构的字典 基本上,我从3列表格开始: 产品Id |客户Id |来源 1 | 1 | A 1 | 2 | A 2 | 1 | A 3 | 1 | B 我想把它转换成一个主字典“DicByUser”,其中键是用户ID,项是另一个字典,其中包含客户机访问的产品的键和源代码项 如果是那样的话,我会的 DicByUser={1:{1:A,2:A,3:B},2:{1:A} 我的方法是遍历初始表的所有行,然后: 使用客户Id Pid产品Id 源头 If DicByUser.Ex

我正在尝试用vba创建一个字典结构的字典

基本上,我从3列表格开始:

产品Id |客户Id |来源

1 | 1 | A

1 | 2 | A

2 | 1 | A

3 | 1 | B

我想把它转换成一个主字典“DicByUser”,其中键是用户ID,项是另一个字典,其中包含客户机访问的产品的键和源代码项

如果是那样的话,我会的

DicByUser={1:{1:A,2:A,3:B},2:{1:A}

我的方法是遍历初始表的所有行,然后:

使用客户Id

Pid产品Id

源头

If DicByUser.Exists(Cid) Then
    If DicByUser.Item(Cid).Exists(Pid) Then
        'We do something on the item
    Else
        DicByUser.Item(Cid).Add Pid, source
    End If
 Else
    Dim dicotoadd As New Scripting.Dictionary
    dicotoadd.Add Pid, source
    DicByUser.Add Cid, dicotoadd
奇怪的是,最后一行之前的行给了我一个错误:vba告诉我

Error 457 : this key is already associated with an element of collection
然后,如果我进入调试模式并尝试显示对象dicotoadd中的元素数,我会发现1,而对象是在前面的行中创建的

我相信在我把一本字典放在另一本字典中的方式可能有问题,因为我总是给它起相同的名字,否则我不明白为什么我在上面一行创建的字典已经包含了一个元素

在vba中创建嵌套字典的过程中,我做错了什么

编辑:根据Mat的马克杯建议,将我的代码更改为以下代码即可解决此问题

If DicByUser.Exists(Cid) Then
    If DicByUser.Item(Cid).Exists(Pid) Then
        'We do something on the item
    Else
        DicByUser.Item(Cid).Add Pid, source
    End If
 Else
    Dim dicotoadd As Scripting.Dictionary
    Set dicotoadd = New Scripting.Dictionary
    dicotoadd.Add Pid, source
    DicByUser.Add Cid, dicotoadd
经典的陷阱

  • VBA中变量的最小范围是过程级别
  • 作为过程范围中的新
    更改对象的生存期
下面是一个简单的例子,应该会给你一些启发:

Public Sub DoSomething()

    Dim c1 As New Collection 'notice: As New
    c1.Add "TEST"
    Set c1 = Nothing
    c1.Add "this will NOT throw runtime error 91"

    Dim c2 As Collection
    Set c2 = New Collection
    c2.Add "TEST"
    Set c2 = Nothing
    c2.Add "this WILL throw runtime error 91"

End Sub
您的代码正在将DicByUser声明为新的——它位于
Else
分支内的事实不会改变其作用域,它仍然是过程作用域的局部,并且它不是在Else分支运行时运行的可执行语句


拆分声明和引用分配,您将修复您的错误。

使用后,dim as new似乎未正确发布,请尝试手动发布(设置dicotoadd=nothing),并尝试从Instation拆分声明(dim outside if,然后设置DictoAdd=new scripting.dictionary)