创建对象集合,然后在Excel VBA中查找集合中的匹配项

时间:2015-04-02 21:04:32

标签: excel-vba vba excel

我在这个特定问题上遇到了困难,因为这些是我一次合作的2-3个新概念。我是集合和类的新手,过去只做过动态数组(是的,我知道,很多" Redim Preserves")。这已经足够了,但我终于到了需要更强大功能来处理我的名单的地步。

要设置,我需要创建一个命名动态列表的动态列表,然后按顺序读出它们。

实施例: 想象一下三明治成分的电子表格,其中A列是成分,B列是三明治名称。 (三明治的数量和每个三明治中的成分数量是未知的,因此都是动态的。)

我需要沿着排下去阅读三明治类型。 如果已经有这个名称的三明治,请将该成分添加到该三明治列表的末尾。如果没有,请创建一个新列表。

在它结束时,浏览三明治并打印出每个成分列表。

我想我需要做一个" Sandwiches"收集"三明治"对象和我已经开始了" CSandwich" class,with" Public属性将Name()作为字符串"。但后来我迷失了如何制作一个Ingredients数组甚至是什么数据类型......

由于

1 个答案:

答案 0 :(得分:1)

我同意克鲁姆。 VBA对于许多任务非常方便,但它不适合每项任务。我个人认为它对课程的处理非常笨拙。

下面的代码执行您使用集合但不使用Classes的内容。现在尝试收藏,一旦你对它们感到满意,可以考虑学习课程。您可能还希望调查与集合类似的字典,并且可能更适合您当前的要求。

为了测试和演示我的例程,我创建了一个包含以下内容的工作表:

Sample data

在我输入的时候,我重读了你的问题。我看到我的列被颠倒了,但我决定不解决这个问题。

Sub RecordSandI读取每一行并调用AddSandI以适当地存储行的内容。然后输出集合Sandwich的内容给出:

Sandwich a has ingredients:  1  2  3
Sandwich b has ingredients:  3  4
Sandwich c has ingredients:  1  5  6
Sandwich d has ingredients:  2 

Sandwich是集合的集合。对于每个子集合,第一个元素是三明治名称,其余元素是成分。

正如我之前建议的那样,在尝试更复杂的事情之前,先看看你能走多远。

Option Explicit
Sub RecordSandI()

  Dim InxI As Long
  Dim InxS As Long
  Dim RowCrnt As Long
  Dim Sandwich As New Collection

  With Worksheets("SandI")
    RowCrnt = 2

    Do While .Cells(RowCrnt, 1).Value <> ""
      Call AddSandI(Sandwich, .Cells(RowCrnt, 1).Value, .Cells(RowCrnt, 2).Value)
      RowCrnt = RowCrnt + 1
    Loop

  End With

  For InxS = 1 To Sandwich.Count
    Debug.Print "Sandwich " & Sandwich(InxS)(1) & " has ingredients:";
    For InxI = 2 To Sandwich(InxS).Count
      Debug.Print "  " & Sandwich(InxS)(InxI);
    Next
    Debug.Print
  Next

End Sub
Sub AddSandI(ByRef Sandwich As Collection, ByVal SandwichName As String, ByVal IngredientName As String)

  Dim InxI As Long
  Dim InxS As Long
  Dim SandwichNew As Collection

  For InxS = 1 To Sandwich.Count
    If Sandwich(InxS)(1) = SandwichName Then
      ' This sandwich already recorded
      For InxI = 2 To Sandwich(InxS).Count
        If Sandwich(InxS)(InxI) = IngredientName Then
          'Debug.Assert False
          ' Ingredient already recorded
          Exit Sub
        End If
      Next
      ' New ingredient
      Sandwich(InxS).Add IngredientName
      Exit Sub
    End If
  Next

  ' New sandwich
  Set SandwichNew = New Collection
  SandwichNew.Add SandwichName
  SandwichNew.Add IngredientName
  Sandwich.Add SandwichNew

End Sub