【问题标题】:Add multiple values to Dictionary .VBA向 Dictionary .VBA 添加多个值
【发布时间】:2018-07-23 04:38:54
【问题描述】:

我是 VBA 的绝对新手。我想在字典中添加多个值,以按项目的数量对具有相同值的表进行分组。 所以我有这张桌子

1   10  A5  Text1   Audi1   Auto1   100
2   10  A5  Text1   Audi1   Auto1   100
3   10  A5  Text1   Audi1   Auto1   100
4   10  A4  Text4   Audi4   Auto4   200
5   10  A6  Text5   Audi5   Auto5   300
6   10  A6  Text5   Text5   Text5   300
7   10  A5  Text1   Audi1   Auto1   100
8   10  A4  Text4   Audi4   Auto4   200
9   10  A2  Text9   Audi9   Auto9   50
10  10  A1  Text10  Audi10  Auto10  25

现在我想将它们组合在一起,它应该如下所示:

1   40  A5  Text1   Audi1   Auto1   100    
2   20  A4  Text4   Audi4   Auto4   200    
3   20  A6  Text5   Audi5   Auto5   300    
4   10  A2  Text9   Audi9   Auto9   50    
5   10  A1  Text10  Audi10  Auto10  25

我的实际 VBA 是这样的:

Sub Schaltfläche1_Klicken()

Dim WkSh    As Worksheet
Dim aTemp   As Variant
Dim lZeile  As Long
Dim rZelle  As Range
Dim Dict    As Variant

   Set WkSh = ThisWorkbook.Worksheets("Tabelle1")

   With WkSh ' die Fahrzeuge aus A2:Bn in einen temporären Array schreiben
      aTemp = .Range("B13:G" & .Cells(.Rows.Count, 1).End(xlUp).Row)
   End With

   WkSh.Range("B13:G1000").ClearContents ' den Bereich D2:E100 leeren/löschen

   Set Dict = CreateObject("Scripting.Dictionary")

   On Error Resume Next

'     die Daten an das Dictionary übergeben
   For lZeile = 1 To UBound(aTemp)
      Dict(aTemp(lZeile, 2)) = Dict(aTemp(lZeile, 2)) + aTemp(lZeile, 1)
      Next lZeile
'
'    ausgeben
'
   Set rZelle = WkSh.Cells(13, 2) ' Bereich festlegen wo hingeschrieben werden soll Beispiel: cells(5,1) -> Reihe 5 Spalte 1
'
   Application.EnableEvents = False
   rZelle.Resize(Dict.Count) = WorksheetFunction.Transpose(Dict.Items)
   rZelle.Offset(0, 1).Resize(Dict.Count) = WorksheetFunction.Transpose(Dict.Keys)
   Application.EnableEvents = True

End Sub

然后给我这个输出:

1   40  A5
2   20  A4
3   20  A6
4   10  A2
5   10  A1

有人可以帮助我,以实现我想要的输出。

【问题讨论】:

  • 最好用adodb和SQL求和。然后您需要知道字段名称。
  • Audi 和 Auto 列似乎包含 2 个额外的 Text5 值
  • 删除 On Error Resume Next 以防任何错误被屏蔽。
  • 看看this SQL 解决方案。
  • 原始样本数据中是B13中的1还是10?

标签: vba excel dictionary


【解决方案1】:

使用字典。字典键是从 B:F 列的串联创建的。如果键已存在,则将 A 列值添加到该键的现有值中。

Option Explicit
Public Sub GetTotals()
    Dim inputRange As Range, dict As Object, arr(), i As Long, uniqueKey As String, ws As Worksheet

    Application.ScreenUpdating = False

    Set ws = ThisWorkbook.Worksheets("Sheet1")
    Set inputRange = ws.Range("A1:F10")
    Set dict = CreateObject("Scripting.Dictionary")
    arr = inputRange.Value

    For i = LBound(arr, 1) To UBound(arr, 1)
        uniqueKey = arr(i, 2) & "," & arr(i, 3) & "," & arr(i, 4) & "," & arr(i, 5) & "," & arr(i, 6)
        dict(uniqueKey) = dict(uniqueKey) + arr(i, 1)
    Next i
    Dim key As Variant, tempArr() As String, rowCounter As Long
    rowCounter = inputRange.Offset(inputRange.Rows.Count + 2, 0).Row

    With ws
        For Each key In dict.keys
            .Cells(rowCounter, 1) = dict(key)
            tempArr = Split(key, ",")
            .Cells(rowCounter, 2).Resize(1, UBound(tempArr) + 1) = tempArr
            rowCounter = rowCounter + 1
        Next key
    End With

      Application.ScreenUpdating = True
End Sub

仅输出 2 列并忽略额外不需要的行的版本:

Option Explicit
Public Sub GetTotals()
    Dim inputRange As Range, dict As Object, arr(), i As Long, uniqueKey As String, ws As Worksheet

    Application.ScreenUpdating = False

    Set ws = ThisWorkbook.Worksheets("Sheet1")
    Set inputRange = ws.Range("A1:F10")
    Set dict = CreateObject("Scripting.Dictionary")
    arr = inputRange.Value

    For i = LBound(arr, 1) To UBound(arr, 1)
        If Not (arr(i, 4)) = "Text5" Then
            uniqueKey = arr(i, 2) & "," & arr(i, 3) & "," & arr(i, 4) & "," & arr(i, 5) & "," & arr(i, 6)
            dict(uniqueKey) = dict(uniqueKey) + arr(i, 1)
        End If
    Next i
    Dim key As Variant, tempArr() As String, rowCounter As Long
    rowCounter = inputRange.Offset(inputRange.Rows.Count + 2, 0).Row

    With ws
        For Each key In dict.keys
            .Cells(rowCounter, 1) = dict(key)
            tempArr = Split(key, ",")

            .Cells(rowCounter, 2) = tempArr(0)
            rowCounter = rowCounter + 1
        Next key
    End With

    Application.ScreenUpdating = True
End Sub

版本 1:数据在顶部。数据在底部。

版本 2:2 列;忽略错误。

【讨论】:

  • 它有效但不完全。如何更改要放置新输出的位置。 rowcounter 给了我偏移位置,但我怎么能说我想把输出放在 ws.Cells(26,2) 上?
  • 这一行决定了我从哪里开始输出:rowCounter = inputRange.Offset(inputRange.Rows.Count + 2, 0).Row
  • 简单地说 rowCounter = 26 从第 26 行开始。
  • 但我会接受这个以获得正确答案,因为另一件事只是优化
  • .Cells(rowCounter, 1) = dict(key) 将密钥放在 A 列中,因此如果您想在 B 列中输入密钥,请使用 .Cells(rowCounter, 2) = dict(key) 和.Cells(rowCounter,3) = tempArr(0) 这会将所有内容移到右侧一列。 rowCounter 只是说明从哪一行开始写入。把它放在你想要的任何值上,例如26.
【解决方案2】:

另一个基于 Scripting.Dictionary 的解决方案。

Sub Schaltfläche1_Klicken()
    Dim i As Long, j As Long, tmp As String
    Dim aTemp  As Variant, dict As Object

    With ThisWorkbook.Worksheets("Tabelle1")
        aTemp = .Range(.Cells(13, "B"), .Cells(.Rows.Count, "G").End(xlUp)).Value2
        .Range(.Cells(13, "B"), .Cells(.Rows.Count, "G").End(xlUp)).ClearContents

        Set dict = CreateObject("scripting.dictionary")
        dict.comparemode = vbBinaryCompare

        For i = LBound(aTemp, 1) To UBound(aTemp, 1)
            tmp = Join(Array(aTemp(i, 2), aTemp(i, 3), aTemp(i, 4), aTemp(i, 5), aTemp(i, 6)), ChrW(8203))
            dict.Item(tmp) = dict.Item(tmp) + aTemp(i, 1)
        Next i

        With .Cells(13, "B").Resize(dict.Count, 1)
            .Offset(0, -1).Resize(1, 1) = 1
            .Offset(0, -1).Resize(dict.Count, 1).DataSeries Rowcol:=xlColumns, _
                    Type:=xlLinear, Step:=1, Stop:=dict.Count
            .Value = Application.Transpose(dict.items)
            .Offset(0, 1).Value = Application.Transpose(dict.keys)
            .Offset(0, 1).TextToColumns Destination:=.Offset(0, 1), DataType:=xlDelimited, ConsecutiveDelimiter:=False, _
                                        Other:=True, Tab:=False, Semicolon:=False, Comma:=False, Space:=False, _
                                        OtherChar:=ChrW(8203), FieldInfo:=Array(Array(1, 1), Array(2, 1))
        End With

    End With

End Sub

【讨论】:

    猜你喜欢
    • 2015-01-08
    • 2013-12-24
    • 2013-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-21
    • 2018-10-25
    • 2012-10-02
    相关资源
    最近更新 更多