excel - Excel 中的从属值列表
问题描述
我们在 Excel 中获取以下格式的数据:
正如我们在上面的截图中看到的:
Item1 仅映射到 1 个值 = Data1。(A 栏和 B 栏)
Item2 映射到 Data11 和 Data12。(A 栏和 B 栏)
Item2 Data11 和 Data12 也映射到 Item1.Data1(AB 列和 CD 列)
对于整个映射,我们得到的值
我们想使用 VBA 透视数据并以以下格式显示它(我们有 9 列 Item1 到 Item9。为简单起见,我们在下面只添加了 3 列):
我们进行了头脑风暴,但没有得到任何答案。请帮助我们实现这一目标的最佳方法是什么?
解决方案
创建一个名为的类模块clsObj
来存储父子关系。
Option Explicit
Public UID As String
Public Level As Integer
Public Children As New Collection
Sub addChild(child As clsObj)
Dim bExists As Boolean, n As Long
For n = 1 To Me.Children.Count
If Me.Children(n).UID = child.UID Then
bExists = True
Exit For
End If
Next
If Not bExists Then
Me.Children.add child, child.UID
End If
End Sub
Sub output(rngOut, ByRef ar)
Dim child As Object, iLevel As Integer, n As Integer
iLevel = Me.Level
' clear lower levels
For n = iLevel To UBound(ar)
ar(n) = ""
Next
ar(iLevel) = Me.UID
' print out if lowest level
If Me.Children.Count = 0 Then
For n = 1 To UBound(ar)
rngOut.Offset(0, n - 1) = ar(n)
Next
Set rngOut = rngOut.Offset(1)
Else
For Each child In Me.Children
' recurse down next level
child.output rngOut, ar
Next
End If
End Sub
扫描创建对象的输入表。将对象存储在字典中(每个级别一个)以供后续检索
Option Explicit
Sub process()
Dim wb As Workbook, wsIn As Worksheet, wsOut As Worksheet
Dim iLastRow As Long, r As Long, i As Integer
Dim sUID As String, iLevel As Integer
Set wb = ThisWorkbook
Set wsIn = wb.Sheets("Sheet1")
Dim dict(9) As Object, key, obj1 As clsObj, obj2 As clsObj
For i = 1 To 9
Set dict(i) = CreateObject("Scripting.Dictionary")
Next
iLastRow = wsIn.Cells(Rows.Count, "A").End(xlUp).Row
For r = 1 To iLastRow
iLevel = Mid(wsIn.Cells(r, "A"), 5)
sUID = wsIn.Cells(r, "B")
If dict(iLevel).exists(sUID) Then
Set obj1 = dict(iLevel).Item(sUID)
Else
' new item
Set obj1 = New clsObj
obj1.UID = sUID
obj1.Level = iLevel
dict(iLevel).add sUID, obj1
End If
' child
iLevel = Mid(wsIn.Cells(r, "C"), 5)
sUID = wsIn.Cells(r, "D")
If dict(iLevel).exists(sUID) Then
Set obj2 = dict(iLevel).Item(sUID)
Else
' new item
Set obj2 = New clsObj
obj2.UID = sUID
obj2.Level = iLevel
dict(iLevel).add sUID, obj2
End If
obj1.addChild obj2
Next
' result to sheet2
Dim ar(9) As String, rngOut As Range
Set wsOut = wb.Sheets("Sheet2")
wsOut.Cells.Clear
For iLevel = 1 To 9
wsOut.Cells(1, iLevel) = "Item " & iLevel
Next
Set rngOut = wsOut.Range("A2")
For Each key In dict(1)
dict(1)(key).output rngOut, ar
Next
MsgBox "Done"
End Sub
推荐阅读
- avr - 如何修复错误:在 atmega328p 中,“asm”之前的预期标识符或“(”
- android - Android 工具链 - 为 Android 设备开发
- arrays - 从 mongodb 中的整数文本文件写入以进行排序和查找距离
- javascript - 如果主链接在 HTML 中不可用,如何连接一个主链接和另一个链接?
- c# - 从 Ajax 函数 Web 方法调用 BOT 监听 URL
- sql-server - 使用 Python 将数据框插入 SQL Server 时出错
- android - FirebaseMessagingService 销毁太快
- gatsby - 在 Gatsby 站点中添加 Javascript 脚本
- geoserver - GeoServer 的 SLDService 为 RangedClassifier.getPercentages() 抛出 NoSuchMethodError
- javascript - 如何让我的搜索功能工作以过滤表中的搜索项目?