You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

关闭工作簿致变量失效?VBA嵌套Dictionary数据丢失问题排查

问题根源与解决方案

嘿,这个问题我之前也碰到过!你遇到的“Object Required”错误,核心原因几乎可以确定是:你的obj2字典里存的不是普通的文本/数值,而是指向了已关闭工作簿中的Excel对象(比如Range、单元格或者工作表对象)

当你关闭工作簿后,这些Excel对象的引用就彻底失效了——相当于你拿着一个指向已经被销毁的东西的“地址”,系统找不到对应的对象,自然就抛出了这个错误。虽然你贴的示例代码里存的是字符串"Value21",但你说这不是原始代码,那原始代码肯定是在读取数据时,直接把Excel对象本身存进了字典,而不是提取对象的实际值。举个例子,如果你写的是:

a_obj("key2").Add "key21", wb.Sheets(sh).Range("A1") ' 存的是Range对象引用

而不是:

a_obj("key2").Add "key21", wb.Sheets(sh).Range("A1").Value ' 存的是单元格的值

那工作簿一关,这个引用就成了无效的空指针。

另外,你的主程序里有个小笔误:info.Items("key1")是错的,DictionaryItems方法返回的是所有值的数组,不能直接用键来索引,应该写成info.obj1("key1")才对,估计是你写示例时手滑了。


怎么解决?

1. 存值,不要存对象引用

这是最关键的一步。从工作表读取数据时,一定要提取对象的,而不是对象本身。根据你的需求,可以用.Value(保留单元格格式)、.Value2(更快,不保留格式)或者.Text(显示的文本)。比如:

' 错误:存Range对象
a_obj("key2").Add "key21", wb.Sheets(sh).Range("B2")
' 正确:存单元格的值
a_obj("key2").Add "key21", wb.Sheets(sh).Range("B2").Value2

2. 检查字典里的内容类型

你可以在关闭工作簿前,用TypeName()函数确认字典元素的类型,看看是不是存了Excel对象:

Debug.Print TypeName(info.obj2("key2")("key21"))
' 如果输出是Range/Worksheet之类的,就说明确实存了对象引用

3. 额外的代码优化

  • 你的类模块里obj1obj2声明为Object,虽然能运行,但如果引用了Microsoft Scripting Runtime库(工具→引用里找),可以直接声明为Scripting.Dictionary,这样能获得代码提示和类型检查,减少错误:
    Public obj1 As Scripting.Dictionary
    Public obj2 As Scripting.Dictionary
    
  • 你的ReadFrom方法里,先创建字典又被Get1/Get2的返回值覆盖,这两步是多余的,可以删掉:
    Public Sub ReadFrom(wb As Workbook)
        ' 下面两行可以删掉,Get1/Get2会返回新创建的字典
        ' Set obj1 = CreateObject("Scripting.Dictionary")
        ' Set obj2 = CreateObject("Scripting.Dictionary")
        Set obj1 = Get1(wb, "sheet1")
        Set obj2 = Get2(wb, "sheet2")
    End Sub
    

内容的提问来源于stack exchange,提问作者Helloguys

火山引擎 最新活动