解决VBA循环中所有子Dictionary值被错误更新的问题
问题原因分析
你遇到的问题核心是VBA中对象的引用赋值特性。在你的代码里,当你创建item_dict这个Scripting.Dictionary对象后,把它同时赋值给了status_dict的"used"、"new"、"removed"三个键——但在VBA中,对象变量存储的是对内存中对象的引用,而不是对象的副本。这意味着这三个键指向的是同一个字典实例,所以无论你更新哪个状态下的item数值,另外两个状态里的对应数值都会跟着变化,因为它们本质上是操作同一个字典。
比如你执行test_dict(product_name)(item_status)(item_name) +=1时,不管item_status是used/new/removed,修改的都是同一个item_dict里的值,这就导致了所有状态的数值都被错误同步。
修正后的代码
你需要为每个状态单独创建新的Scripting.Dictionary实例,而不是复用同一个对象。下面是修复后的代码:
Sub example() Set test_dict = New Scripting.Dictionary For i = 1 To 10 product_name = Cells(i, 1).Value item_name = Cells(i, 2).Value item_status = Cells(i, 3).Value If Not test_dict.Exists(product_name) Then Set status_dict = New Scripting.Dictionary ' 为每个状态单独创建新的item字典 Set used_dict = New Scripting.Dictionary used_dict.Add item_name, 0 status_dict.Add "used", used_dict Set new_dict = New Scripting.Dictionary new_dict.Add item_name, 0 status_dict.Add "new", new_dict Set removed_dict = New Scripting.Dictionary removed_dict.Add item_name, 0 status_dict.Add "removed", removed_dict test_dict.Add product_name, status_dict Else ' 检查当前状态的字典中是否存在该item,不存在则添加初始值0 If Not test_dict(product_name)(item_status).Exists(item_name) Then test_dict(product_name)(item_status).Add item_name, 0 End If End If ' 累加对应状态下的item数量 test_dict(product_name)(item_status)(item_name) = test_dict(product_name)(item_status)(item_name) + 1 Next End Sub
关键修改点说明
- 每个状态单独创建字典实例:不再共用一个
item_dict,而是为"used"、"new"、"removed"分别创建独立的Scripting.Dictionary对象,确保它们的操作互不影响。 - 新增item存在性检查:在else分支中,添加了对当前状态字典中是否存在item的判断——因为原代码只在创建product时添加了当前循环的item,但后续遇到同product下其他item时会报错(键已存在),所以需要先检查再添加初始值。
验证预期结果
修复后,product1的统计结果会完全符合你的预期:
- "used"下:item1=1,item3=0
- "new"下:item1=0,item3=1
- "removed"下:item1=0,item3=2
其他产品的统计也会正常工作,每个状态的数值都是独立统计的。
内容的提问来源于stack exchange,提问作者GPost
相关产品推荐
相关产品推荐

