【问题标题】:3D Datastructure with Index带索引的 3D 数据结构
【发布时间】:2018-08-14 15:45:32
【问题描述】:

这是我关于 stackoverflow 的第一个问题,我非常愿意接受有关如何/在何处/何时提出更好的问题以及如何更好地为 stackoverflow 做出贡献的反馈。

背景:
我的最终目标是在各个测试实验室按日期绘制预计的设备使用情况。

我在多个实验室使用相同的设备,我正在创建一个表格,显示每个实验室的设备使用情况的未来预测。

我的开始:
我有一个包含多个工作表的 Excel 文档,每个工作表都包含有关在什么时间段内哪个测试机构将使用哪些设备的信息。

我的目标:
为每个测试实验室创建设备使用图表。该图表将显示在给定日期每件设备中有多少正在使用。我的目的是为每种类型的设备制作一个图表系列,以日期为 X 轴,在 Y 轴上使用该设备的件数。

到目前为止我做了什么:
我已经编写了循环遍历所有信息表的代码,并创建了每个唯一测试实验室名称的 vba 集合和我想要跟踪的每个唯一设备的单独 vba 集合。此代码还查找使用任何设备的第一个日期和最后一个日期。

帮助请求:
因为我基本上有三个“维度”——测试实验室、设备部件和设备使用日期——我计划使用 3D 数组来聚合我的所有数据并为我的使用图提供源。该数组的一维是设备,第二维是日期,第三维是测试实验室。

但是,在我考虑过这个实现时,它似乎相当笨拙。它将保存我的所有数据,但据我所知,我不能通过键或标签来引用数组的元素。我必须创建单独的 2D 数组来保存 3D 数组的每个维度的索引标签。

Excel VBA 中是否有支持每个维度的索引键的 3D 数据结构?

搜索和尝试失败:
我首先尝试创建一个独特的数组来保存设备和使用日期,每个数组都以一个独特的测试实验室命名。我从这篇文章中了解到,我无法在 sub:Naming an array using a variable 中动态创建和命名未定义数量的新数组。

然后我研究了是否可以使用我已经创建的集合以某种方式充当数组索引的标签,但似乎我无法通过键找到集合索引。每次我想引用 3D 数组中的元素时,我都必须遍历集合以查找索引:Retrieve the index of an object stored in a collection using its key (VBA)

【问题讨论】:

  • 您可能会沿着 vba 中的结构或类的路线查看。它们是一种将多条相关信息保存在一起的方法,您可以创建一个列表或集合。查看这篇文章,看看这是否是你所追求的。 stackoverflow.com/questions/12414168/…
  • 可以考虑使用嵌套的scripting.dictionariescollections。外部 Dictionary 将实验室 ID 作为键保存,每个项目都是另一个 dictionary,将设备 ID 作为键和日期作为项目。
  • 谢谢你们的cmets!我正在尝试创建一个自定义数据类型,该类型在 Jeremy 的建议文章中建模,其中包含 Victor K 和 HackSlash 建议的类型中的 scripting.dictionaries。当我得到它的工作时,我应该如何展示解决方案?我会回答我自己的问题吗?
  • 是的。如果你愿意,你可以回答你自己的问题。

标签: arrays vba excel


【解决方案1】:

我从收到的所有 cmets 和答案中实现了信息。谢谢 Jeremy、Victor K 和 HackSlash!

简而言之,这是对我有用的解决方案:用户定义数据类型的数组,其中包含包含脚本字典的用户定义数据类型的数组,即字典数组的数组。我还创建了用于检索数据的参考字典。 (参见下面的工作示例)

首先,要在 VBA 中使用脚本字典,请转到工具 > 参考并选中“Microsoft 脚本运行时”旁边的框。我在这里学到了这个:Does VBA have Dictionary Structure?。我还了解到,如果分发了工作表,则包含此设置(其他人不必输入 VBA 并选中该框才能使用您的工作表):http://www.snb-vba.eu/VBA_Dictionary_en.html

Public Type ItemTracked
    ItemName As String
    UseDates As Scripting.Dictionary
End Type

Public Type TrackingStructure
    TestLab As String
    TrackedItems() As ItemTracked
End Type

Sub Tracking()

Dim TrackingArr() As TrackingStructure

'**************
'Example Data
'**************
    'Create array of example dates
    Dim DateArray As Variant
    DateArray = Array(43164, 43171, 43178) 'Excel date codes for 3/5/2018, 3/12/2018, and 3/19/2018

    'Create array of example equipment
    Dim EquipArray As Variant
    EquipArray = Array("Cooling Pump", "Heating Pad", "Power Supply")

    'Create array of example number of pieces of equipment in use
    Dim UseArray As Variant
    UseArray = Array(0, 1, 2)

    'Create array of example test lab names
    Dim LabNames As Variant
    LabNames = Array("LabABC", "Lab123", "LabDOREMI")

'**************
'Creating and Populating Data Structure
'**************

    'Create array of TrackingStructure Type with space to track test labs
    ReDim TrackingArr(UBound(LabNames))

    'Loop through TrackingArr to populate usage for each test lab
    For i = LBound(TrackingArr) To UBound(TrackingArr)

        'Record lab name
        TrackingArr(i).TestLab = LabNames(i)

        'Redimension size of TrackedItems to accomodate example equipment
        ReDim TrackingArr(i).TrackedItems(UBound(EquipArray))

            'Loop through EquipArray for each test lab
            For j = LBound(EquipArray) To UBound(EquipArray)
                Set TrackingArr(i).TrackedItems(j).UseDates = New Scripting.Dictionary
                TrackingArr(i).TrackedItems(j).ItemName = EquipArray(j)

                'Loop through dates and usage for each piece of equipment
                For k = LBound(DateArray) To UBound(DateArray)
                    'Populate date and equipment use
                    TrackingArr(i).TrackedItems(j).UseDates.Add DateArray(k), UseArray(k)
                Next k
            Next j
    Next i

'**************
'Referencing Data
'**************

'Create and Populate Dictionaries for Use in Referring to Data
Set LabNamesRef = New Scripting.Dictionary
Set EquipArrayRef = New Scripting.Dictionary

For i = LBound(TrackingArr) To UBound(TrackingArr)
    LabNamesRef.Add TrackingArr(i).TestLab, i
Next i

For i = LBound(EquipArray) To UBound(EquipArray)
    EquipArrayRef.Add EquipArray(i), i
Next i

'Demonstration Print of Entire Data Structure
For i = LBound(TrackingArr) To UBound(TrackingArr)
    Debug.Print "Lab Name: " & TrackingArr(i).TestLab
    For j = LBound(TrackingArr(i).TrackedItems) To UBound(TrackingArr(i).TrackedItems)
        Debug.Print TrackingArr(i).TrackedItems(j).ItemName
        For k = 0 To TrackingArr(i).TrackedItems(j).UseDates.Count - 1
            Debug.Print TrackingArr(i).TrackedItems(j).UseDates.Keys(k), TrackingArr(i).TrackedItems(j).UseDates.Items(k)
        Next k
    Next j
Next i

'Access One Example Entry
Debug.Print "Lab Name:" & TrackingArr(LabNamesRef("Lab123")).TestLab
Debug.Print "Equipment:" & TrackingArr(LabNamesRef("Lab123")).TrackedItems(EquipArrayRef("Cooling Pump")).ItemName
Debug.Print "Usage on Date 43164: " & TrackingArr(LabNamesRef("Lab123")).TrackedItems(EquipArrayRef("Cooling Pump")).UseDates(43164)

End Sub

【讨论】:

    【解决方案2】:

    如果您需要按键调用集合,则应将该集合声明为字典。

    Dim dict As Object
    Set dict = CreateObject("Scripting.Dictionary")
    dict(Key) = Value
    

    它比集合强大得多。我希望这会有所帮助。

    完整信息: https://excelmacromastery.com/vba-dictionary/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-10
      • 1970-01-01
      • 2012-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-16
      相关资源
      最近更新 更多