excel - 不同长度的嵌套 UDT
问题描述
你好美丽的人们,
我试图在 vba 中创建嵌套的 UDT,以便子 UDT 可以根据情况有多个实例。
下面的示例更好地解释了我正在尝试做的事情:
样本数据:
+----------+-------------+
| Customer | Transaction |
+----------+-------------+
| A | 1 |
| B | 2 |
| C | 3 |
| C | 4 |
| C | 5 |
| D | 6 |
| E | 7 |
| F | 8 |
| D | 9 |
| E | 10 |
+----------+-------------+
期望的结果:
- 客户(1).transaction(1).transactionid = 1
- 客户(2).transaction(1).transactionid = 2
- 客户(3).transaction(1).transactionid = 3
- 客户(3).transaction(2).transactionid = 4
- 客户(3).transaction(3).transactionid = 5
- 客户(4).transaction(1).transactionid = 6
- 客户(4).transaction(2).transactionid = 9
- 客户(5).transaction(1).transactionid = 7
- 客户(5).transaction(2).transactionid = 10
- 客户(6).transaction(1).transactionid = 8
我最初尝试使用类,因为我需要为 UDT 的每个“实例”跟踪许多变量。但是,由于我的数据太大,使用类的时间太长(几分钟)。
切换到 UDT 将我的运行时间缩短到几秒钟,但需要进行一些调整。
据我了解,我可以按照我尝试的方式传递 UDT 的多个“实例”,但我应该将其作为未定义长度的填充数组。不过,我无法真正解决这个问题,至少不足以提出解决方案。
我是否需要循环遍历所有数据 n 次以创建 n 个数组(在示例中为 n = 6)?这将对性能造成严重影响。有没有更优雅的解决方案?
下面的代码是我最近尝试使用的代码。
Option Explicit
Public Type Child
transactionid As String
det As String
End Type
Public Type Parent
children As Child
End Type
Sub test()
ReDim transaction(1 To 10) As Child
ReDim customer(1 To 6) As Parent
Dim wk As Worksheet
Set wk = ThisWorkbook.Sheets(1)
Dim c As Integer
For c = 1 To 10
transaction(c).det = wk.Range("G" & c + 1).Value
transaction(c).transactionid = wk.Range("h" & c + 1).Value
Next c
Dim j As Integer
Dim i As Integer
j = 1
For i = 1 To 6
If customer(i).children(j).transactionid <> "" Then
'I don't even know
End If
Next i
End Sub
我得到一个
编译错误“预期数组”
在
customer(i).children(j).transactionid
解决方案
您可以为此使用字典,不需要 UDT 或自定义类。如果您真的想使用其中一个,我们可以使用类似的概念使其工作,但这里是您使用字典的方法,以及如何遍历字典中的所有内容以获取信息。它也应该很快地填充字典:
Sub tgr()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(1)
With ws.Range("G2", ws.Cells(ws.Rows.Count, "H").End(xlUp))
If .Row < 2 Then Exit Sub 'No data
Dim aData() As Variant
aData = .Value
End With
Dim hCustomers As Object
Set hCustomers = CreateObject("Scripting.Dictionary")
Dim i As Long
Dim hTemp As Object
For i = LBound(aData, 1) To UBound(aData, 1)
If Not hCustomers.Exists(aData(i, 1)) Then
Set hTemp = CreateObject("Scripting.Dictionary")
Else
Set hTemp = hCustomers(aData(i, 1))
End If
hTemp(hTemp.Count + 1) = aData(i, 2)
Set hCustomers(aData(i, 1)) = hTemp
Set hTemp = Nothing
Next i
Dim vCustomer As Variant
Dim vTransactionID As Variant
For Each vCustomer In hCustomers.Keys
For Each vTransactionID In hCustomers(vCustomer).Keys
MsgBox "Customer: " & vCustomer & Chr(10) & _
"Transaction ID: " & vTransactionID & Chr(10) & _
"Transaction: " & hCustomers(vCustomer)(vTransactionID)
Next vTransactionID
Next vCustomer
End Sub
推荐阅读
- apache - 域不能与 www 一起使用,但在没有 www 的情况下也可以使用
- python - Kivy:奇怪的按钮 on_touch_down 行为?
- c# - 整数到字母字符串 (a, A, b, B, ..., z, Z, aa, Aa, ba, Ba, ... za, zA, aA, AA, ...)
- c - 项目不会在 Codeblocks IDE 中链接
- c# - 反射:读取一个对象的List类型属性,包含另一个对象
- python - 基于平均值对长向量进行下采样
- c# - 无法将 IdentityServer4 NuGet 包正确添加到 ASP.NET Core 项目,并且 VS Code 未显示智能感知
- angular - 如何使样式或样式表可用于子组件
- xamarin.forms - 在 23 之前的版本中,什么等同于 LayerDrawable.SetLayerInsetRight?
- amazon-web-services - 如何使用 amazon lex 保持转换的上下文?