将词典放入课堂

时间:2017-04-06 17:49:41

标签: vba excel-vba excel

几个星期前,我收到了关于如何在这个位置制作通用课程模块的神话般的答案:Class "let" stuck in infinite loop

说实话,我仍然不知道这么多,因为我的vba知识100%都是自学成才的,并且从几年前开始,从一个学期的C学期开始,只剩下一小部分通用编程逻辑。但我认为我对此有很好的把握,因为这是一个很好的解释。我现在正试图将其应用于我的课程中的字典并遇到麻烦。

我的课程模块如下:

Option Explicit

Private Type categories
    Temp As scripting.Dictionary
    Humid As scripting.Dictionary
    Wind As scripting.Dictionary
End Type

Private this As categories

Public Sub Initialize()
    Set this.Temp = New scripting.Dictionary
    Set this.Humid = New scripting.Dictionary
    Set this.Wind = New scripting.Dictionary
End Sub

Public Property Get Temp(ByVal HourIndex As Long) As Double
    Temp = this.Temp(HourIndex)
End Property

Public Property Let Temp(ByVal HourIndex As Long, ByVal Value As Double)
    this.Temp(HourIndex) = Value
End Property

Public Property Get Humid(ByVal HourIndex As Long) As Double
    Humid = this.Humid(HourIndex)
End Property

Public Property Let Humid(ByVal HourIndex As Long, ByVal Value As Double)
    this.Humid(HourIndex) = Value
End Property

Public Property Get Wind(ByVal HourIndex As Long) As Double
    Wind = this.Wind(HourIndex)
End Property

Public Property Let Wind(ByVal HourIndex As Long, ByVal Value As Double)
    this.Wind(HourIndex) = Value
End Property

然后我尝试使用set tester = new WeatherData(模块名称)和Initialize在即时窗口中对此进行测试。那没用。然后我将Initialize修改为:

Public Sub Initialize(ByVal variable As categories)
    Set variable.Temp = New scripting.Dictionary
    Set variable.Humid = New scripting.Dictionary
    Set variable.Wind = New scripting.Dictionary
End Sub

并输入Initialize tester,但这也不起作用("编译错误:Sub或函数未定义")。

所以,结束问题:我如何将三个字典放入类模块中?

编辑:我是个傻瓜。以下并没有真正解决问题本身,但它确实至少绕过它,以至于我不必承认它:

Option Explicit

Private Type categories
    Temp(23) As Double
    Humid(23) As Double
    wind(23) As Double
End Type

Private this As categories

Public Property Get Temp(ByVal HourIndex As Long) As Double
    Temp = this.Temp(HourIndex)
End Property

Public Property Let Temp(ByVal HourIndex As Long, ByVal Value As Double)
    this.Temp(HourIndex) = Value
End Property

Public Property Get Humid(ByVal HourIndex As Long) As Double
    Humid = this.Humid(HourIndex)
End Property

Public Property Let Humid(ByVal HourIndex As Long, ByVal Value As Double)
    this.Humid(HourIndex) = Value
End Property

Public Property Get wind(ByVal HourIndex As Long) As Double
    wind = this.WindChill(HourIndex)
End Property

Public Property Let wind(ByVal HourIndex As Long, ByVal Value As Double)
    this.wind(HourIndex) = Value
End Property

tl; dr:make数组而不是字典,并完全删除初始化。你的"键"别无选择,只能成为数字,但它起作用,至少。我真的很想知道一个实际的解决方案,如果有人这么倾向,但我遇到的具体问题就解决了。

2 个答案:

答案 0 :(得分:4)

似乎您想要实现索引属性

简化为最低限度:

Option Explicit
Private values As Scripting.Dictionary

Private Sub Class_Initialize()
    Set values = New Scripting.Dictionary
End Sub

Public Property Get Something(ByVal key As String) As Double
    Something = values(key)
End Property

Public Property Let Something(ByVal key As String, ByVal value As Double)
    values(key) = value
End Property

您可以将字典安全地封装为类的实现细节(例如,外部代码无法将它们设置为Nothing),并公开索引的Get + Let属性每个封装的字典,它将索引(/ key)作为参数。

对于WeatherData类,这意味着您可以像这样填充数据:

Set data = New WeatherData
With data
    .Temp("day 1") = 76
    .Temp("day 2") = 78
    .Humid("day 1") = 0.55
    .Humid("day 2") = 0.61
    .Wind("day 1") = 0.92
    .Wind("day 2") = 1.27
End With

然后使用"day 1"检索data.Temp("day 1")的温度。

对于初始化方法,需要从类的实例调用它 - 作为实例方法

因此,您应该Initialize tester而不是tester.Initialize

无论是将内部封装存储设置为数组,Collection还是Dictionary都不会对调用代码产生任何影响 - 它是一个封装的实现细节:您的类也可以将数据存储在.csv文件或数据库,如果需要。

答案 1 :(得分:0)

在这种情况下,您应该使用后期绑定:

Private Type categories
    Temp As Object
    Humid As Object
    Wind As Object
End Type

Private this As categories

Public Sub Initialize()
    Set this.Temp = CreateObject("Scripting.Dictionary")
    Set this.Humid = CreateObject("Scripting.Dictionary")
    Set this.Wind = CreateObject("Scripting.Dictionary")
End Sub

此外,您不能将Let与多个参数一起使用。你应该使用一个函数来做到这一点:

Public Function SetTemp(ByVal HourIndex As Long, ByVal Value As Double)
    this.Temp(HourIndex) = Value
End Function

为了运行这个,我使用了:

Sub test()
    Dim multi As Dictionaries
    Set multi = New Dictionaries

    multi.Initialize

    multi.SetTemp 13, 25.522
    Debug.Print multi.Temp(13)
End Sub

我的类模块名为Dictionaries。所以基本上使用后期绑定并将所有多参数let函数更改为简单函数。