向脚本字典问题VBA添加三个变量

时间:2019-07-05 08:14:20

标签: excel vba dictionary

我刚接触VBA(2个月),我试图向脚本字典中添加三个变量以重新格式化Excel表,但我遇到了错误。

我尝试通过

添加三个变量
countrydict.Add country, data, time

但是我收到一条错误消息

Run-time error '450':
Wrong number of arguments or invalid property assignment

但是如果我写

还是可以的
countrydict.Add country, data 'or 
countrydict.Add country, time




Dim lastrow As Long
Dim iter As Long
Dim diter As Long
Dim countrydict As Object
Dim country As String
Dim data As String
Dim time As String
Dim key As Variant
Dim i As Long

Const StartRow As Byte = 2
lastrow = Range("A" & StartRow).End(xlDown).Row

Set countrydict = CreateObject("Scripting.Dictionary")

Dim diter2 As Long, arr, arr2

With ActiveSheet
For iter = 2 To lastrow
    country = Trim(.Cells(iter, 1).Value) '<<<<<
    data = Trim(.Cells(iter, 2).Value) '<<<<<
    time = Trim(.Cells(iter, 3).Text) '<<<<<
    If countrydict.Exists(country) Then
        If Not InStr(1, countrydict(country), data) > 0 Then

            countrydict(country) = countrydict(country) & _
                                   "|" & data & "/" & time
        End If
    Else
        countrydict.Add country, data, time '<<<<<<<
    End If
Next
    iter = 2
      For Each key In countrydict
    .Cells(iter, 1).Value = key & ":"
    .Cells(iter, 1).Font.Bold = True
    .Cells(iter, 1).Font.ColorIndex = 30
    iter = iter + 1
    arr = Split(countrydict(key), "|")
    For diter = 0 To UBound(arr)
        arr2 = Split(arr(diter), "/")
        .Cells(iter, 1).Value = arr2(0)
        .Cells(iter, 2).Value = arr2(1)
    Next diter
Next key
End With
End Sub

预期结果是以这种格式重新格式化表格

"A"  "B"     "C"
EU  Sales   10:00
EU  Tax     12:00
USA Sales   09:00
USA Tax     10:00

以这种格式

EU: 
Sales 10:00
Tax   12:00 
USA:
Sales 09:00
Tax   10:00

非常感谢您的帮助。几天来我一直在努力解决这个问题...

2 个答案:

答案 0 :(得分:2)

VBA具有字典结构。 Dictionary is an object,并且可以通过早期绑定(例如Set countrydict = CreateObject("Scripting.Dictionary"))或通过后期绑定来引用,指的是Microsoft脚本运行时(在VBEditor>其他>库):

enter image description here

后者的优点是速度更快,按 Ctrl + space 可以看到Intelli-Sense:

enter image description here

关于字典中具有多个变量的问题,则可能有一个包含这些变量的数组:

Sub MyDictionary()

    Dim myDict As New Scripting.Dictionary

    If Not myDict.Exists("Slim") Then
        Debug.Print "Adding Slim"
        myDict.Add "Slim", Array("Eminem", "has", "a", "daughter!")
    End If

    If Not myDict.Exists("Barcelona") Then
        Debug.Print "Adding Barcelona"
        myDict.Add "Barcelona", Array("I", "have", "been there", 2018)
    End If

    If Not myDict.Exists("Barcelona") Then
        myDict.Add "Barcelona", Array("I", "have", "been there", 2018)
    Else
        Debug.Print "Barcelona already exists!"
    End If

    'Keys
    Dim key As Variant
    For Each key In myDict.Keys
        Debug.Print "--------------"
        Debug.Print "Key -> "; key
        Dim arrItem As Variant
        For Each arrItem In myDict(key)
            Debug.Print arrItem
        Next
    Next key

End Sub

这是代码的结果:

Adding Slim
Adding Barcelona
Barcelona already exists!
--------------
Key -> Slim
Eminem
has
a
daughter!
--------------
Key -> Barcelona
I
have
been there
 2018 

如果字典的值不是数组,例如如果在myDict.Add "notArray", 124处添加内容,则在尝试打印数组时会弹出错误。使用IsArray built-in function可以避免这种情况。

答案 1 :(得分:1)

另一种可能性是创建一个新类来存储您的数据。将数据存储在此类的实例中,然后将此对象传递给字典。

这样,您可以通过事件扩展类以返回其他内容,例如,将所有值组合为字符串等。使用公共属性,您甚至可以设置输入验证以及不进行输入验证,但这可能不止于此。现在需要。
我将“类”保持在绝对最小值,通常,类中的公共变量是不好的,但是由于我们仅将其用作自定义数据类型,所以这无关紧要。

编辑:我对该类进行了一些更新,以显示更多功能,但这里以旧的示例为例。

标准模块“模块1”:

Option Explicit

Sub fillDict()

    Dim adict As Scripting.Dictionary
    Set adict = New Dictionary

    Dim info As myRegionData
    Dim iter As Long

    For iter = 0 To 10
        Set info = New myRegionData

        info.Region = "someRegion" & iter
        info.data = "someData" & iter
        info.Time = "someTime" & iter

        adict.Add info.Region, info

    Next iter

    Dim returnInfo As myRegionData
    Set returnInfo = adict.Item("someRegion1")

    With returnInfo
        Debug.Print .Region, .data, .Time       'someRegion1   someData1     someTime1
        Debug.Print .fullSentence               'At someTime1 I was in someRegion1 and did someData1
    End With

End Sub

类模块(简单)“ myRegionData”:

Option Explicit

Public Region As String
Public data As String
Public Time As String

类模块(扩展)“ myRegionData”:

Option Explicit

Private Type TmyRegionData
    'More about this structure:
    'https://rubberduckvba.wordpress.com/2018/04/25/private-this-as-tsomething/
    Region As String
    data As String
    Time As String
End Type
Private this As TmyRegionData


Public Property Get Region() As String
    Region = this.Region
End Property
Public Property Let Region(value As String)
    this.Region = value
End Property

Public Property Get data() As String
    data = this.data
End Property
Public Property Let data(value As String)
    this.data = value
End Property

Public Property Get Time() As String
    Time = this.Time
End Property
Public Property Let Time(value As String)
    this.Time = value
End Property


Public Function getFullSentence() As String
    getFullSentence = "At " & Time & " I was in " & Region & " and did " & data
End Function