VBA类模块无法存储数组数据,JSON反序列化为对象问题
报错原因说明
- VBA不允许在类模块外部直接对类的公共数组成员、或存储数组的Variant成员执行
ReDim操作,ReDim的操作对象只能是当前作用域内直接声明的数组变量,类的公共成员属于类的作用域,外部无权直接重定义它的维度。 - 你写的
ReDim MyFancyCat.Socks(socksLength) As FancySocks报成员未找到,是因为你试图对Variant类型的公共字段直接指定类型重定义,Variant可以存储数组,但你不能在类外部给它重定义的时候指定强类型。
可行方案(完全满足强类型、智能提示、层级嵌套需求)
方案1:Collection封装(写法最简单,完全匹配你的调用习惯)
这种方式和C#的List用法几乎一致,智能提示完整,支持嵌套结构:
- FancySock类模块(你可以按需添加其他属性)
' FancySock 类模块 Public Colour As String Public Size As Long ' 嵌套属性可以用同样的逻辑实现
- FancyCat类模块
' FancyCat 类模块 Public Name As String Public Age As Long ' 私有存储袜子集合 Private m_Socks As Collection ' 类初始化时自动创建集合 Private Sub Class_Initialize() Set m_Socks = New Collection End Sub ' 对外暴露Socks集合,直接支持Count、按索引取值、Add等方法 Public Property Get Socks() As Collection Set Socks = m_Socks End Property
- 调用逻辑(和你C#的伪代码逻辑完全对应)
Sub JsonToObject() Dim JSONData As Object ' 假设这是你解析完成的JSON对象 Dim MyFancyCat As New FancyCat ' 基础属性赋值 MyFancyCat.Name = JSONData("Name") MyFancyCat.Age = JSONData("Age") ' 填充袜子集合 Dim sockItem As Object For Each sockItem In JSONData("Socks") Dim tmpSock As New FancySock tmpSock.Colour = sockItem("Colour") tmpSock.Size = sockItem("Size") ' 直接Add即可,不需要提前计算长度 MyFancyCat.Socks.Add tmpSock Next sockItem ' 调用测试,全智能提示 Debug.Print MyFancyCat.Name Debug.Print MyFancyCat.Socks.Count Debug.Print MyFancyCat.Socks(1).Colour End Sub
方案2:私有数组+属性封装(纯强类型无隐式转换)
如果你完全不想用Collection,要纯数组实现可以用这个方案:
' FancyCat 类模块 Public Name As String Public Age As Long Private m_Socks() As FancySock ' 按索引取袜子元素,支持FancySock的属性智能提示 Public Property Get Socks(Index As Long) As FancySock Set Socks = m_Socks(Index) End Property ' 按索引赋值袜子元素 Public Property Set Socks(Index As Long, Value As FancySock) Set m_Socks(Index) = Value End Property ' 袜子总数,对应你要的Count属性 Public Property Get SocksCount() As Long On Error Resume Next SocksCount = UBound(m_Socks) - LBound(m_Socks) + 1 If Err.Number <> 0 Then SocksCount = 0 End Property ' 初始化数组长度 Public Sub InitSocks(Length As Long) ReDim m_Socks(1 To Length) ' 可以根据习惯改成0到Length-1 End Sub ' 新增袜子的方法,对应List的Add Public Sub AddSock(Sock As FancySock) Dim currentCount As Long: currentCount = Me.SocksCount If currentCount = 0 Then ReDim m_Socks(1 To 1) Else ReDim Preserve m_Socks(1 To currentCount + 1) End If Set m_Socks(currentCount + 1) = Sock End Sub
嵌套数组处理
FancySock内部如果有嵌套数组/集合,完全可以用和上面相同的逻辑实现,VBA的数组/Collection都支持正常的引用传递,不会出现你担心的赋值问题。
内容的提问来源于stack exchange,提问作者NibblyPig
相关产品推荐
相关产品推荐

