VBA动态填充嵌套的数据结构



我有几个SQL表,其中一些是链接的,我想查询一次,并在本地存储在一个变量中。我无法提前预测数据的长度,所以我需要一个动态的数据结构。

我正在查询的示例数据:

表1

NameA
Red
Green
Blue

表2

NameA   NameB
Red     A
Red     B
Red     C
Blue    D
Blue    E
Green   F

表3

NameA   NameC
Red     One
Blue    Two
Blue    Three
Blue    Four
Blue    Five
Green   Six
Green   Seven

我需要能够根据NameA值过滤和访问NameB和NameC。我更喜欢嵌套的字典结构,我可以查询如下:

Table1("0") 'will equal "Red"
Table2("Red")("0") 'will equal "A"
Table2("Blue")("1") 'will equal "E"
Table3("Green")("1") 'will equal "Seven"
'note: point here is data structure, not order of results

我尝试过使用VBA的嵌套词典,但一直无法绕过缺少"深度复制"功能的问题。我写了一个算法:

With SqlQueryResult
i = 0
Do Until .EOF
Call Table1.Add(CStr(i), .Fields(0).Value)
i = i + 1
.MoveNext
Loop
End With
For Each key In Table1.Keys
SqlQueryResult = GetResultsFromQuery(SELECT NameB WHERE NameA = Table1(key))
With SqlQueryResult
i = 0
Do Until .EOF
Call TempDict.Add(CStr(i), .Fields(0).Value)
i = i + 1
.MoveNext
Loop
End With
Set Table2(Table1(key)) = TempDict
TempDict.RemoveAll
Next key

不幸的是,将一个Dict分配给另一个Dict只会设置一个引用,实际上并没有复制数据——当我删除TempDict时,Table2中的嵌套数据也会被删除。

我也不能在嵌套结构中的每个"分支"都有一个新的字典,因为我需要这些数据在模块级范围内可用,因此需要在程序执行之前在模块顶部定义这些数据。

我看过多维动态数组——它们不能像字典一样分配给父结构。我也无法预测这些表中每一个的大小,例如,表1的大小可能是5/20/100/等,红色可能有2/5/100/等结果,蓝色有1/20/等结果,表2中有。Redim只适用于数组中的单个维度。

我也简要地看了一下Collections,我不确定这些是否可行。

我对类没有太多经验,我宁愿避免一个非常复杂的过程——如果我将来需要的话,我希望可以很容易地将链接和未链接的数据(即链接到表1的数据,如表2和表3,而不是与任何其他表无关的独立数据(添加到这个程序中。(我的"easy"基准是python中的pandas数据帧(。

一个用于脚本字典的简单包装器类,它实现了一个克隆方法。这应该可以很好地处理基元数据类型。

Option Explicit
Private Type State
Dict                               As scripting.Dictionary
End Type

Private s                              As State
Private Sub Class_Initialize()
Set s.Dict = New scripting.Dictionary
End Sub

Public Function Clone()
Dim myClone As scripting.Dictionary
Set myClone = New scripting.Dictionary
Dim myKey As Variant
For Each myKey In s.Dict
myClone.Add myKey, s.Dict.Item(myKey)
Next
Set Clone = myClone
End Function

Public Property Get Item(ByVal Key As Variant) As Variant
Item = s.Dict.Item(Key)
End Property
Public Property Set Item(ByVal Key As Variant, ByVal Value As Variant)
s.Dict.Item(Key) = Value
End Property

Public Sub Add(ByVal Key As Variant, ByVal Item As Variant)
s.Dict.Add Key, Item
End Sub

你现在可以说了

Set Table2.Item(Table1.Item(key)) = TempDict.Clone

最新更新