获取类的集合属性会获取另一个类的另一个类的属性吗?

时间:2018-01-23 18:52:57

标签: vba excel-vba excel

我想首先感谢大家在过去几个月中给予我的帮助!我已经从不知道如何访问Excel中的VBA IDE到编写完全集成的分析程序进行工作。没有社区,我无法做到这一点。

我目前正在尝试彻底检查我在学习如何使用VBA编写代码时编写的数据分析程序的第一次迭代。虽然目的很明确,但对我自己来说真的很清晰,但代码工作正常;但是一团糟。从本网站的人们那里,我选择了马丁的清洁代码,并阅读了如何尝试成为更好的程序员的阅读材料。

从马丁的清洁代码中,给我留下了深刻的印象,我优先考虑抽象和解耦我的代码以允许更高程度的维护和模块化。我发现这很困难,因为在我的薪资等级之上要求的非常小的变化将需要大量并且令人困惑的重写!我试图消除这个问题。

我试图用单一责任类重写我的代码(至少,在可能的情况下),我有点困惑。如果我的问题不清楚或者我使用了错误的术语,我会道歉。我希望能够生成特定字符串的集合(我们的检测器的名称是特定的),而不是来自我实验室的原始仪器数据文件的重复。此功能的目的是在类中组合一组元数据,并使用它来标准化我们的文件系统,并防止新手和旧手在使用分析程序时出现文书错误。

测试初始化​​子程序如下。它弹出一个userform,要求用户选择rawdatafiles类中三个文件的文件路径;然后它杀死userform以释放内存。元数据对象当前用于测试,当我得到我想要的输出时将被正确地重写:

Sub setup()
GrabFiles.Show
Set rawdatafiles = New cRawDataFiles
rawdatafiles.labjobFile = GrabFiles.tboxLabJobFile.value
rawdatafiles.rawdatafirstcount = GrabFiles.tboxOriginal.value
rawdatafiles.rawdatasecondcount = GrabFiles.tboxRecount.value
Set GrabFiles = Nothing

Dim temp As cMetaData
Set temp = New cMetaData
temp.labjobName = rawdatafiles.labjobFile 
'this works fine!
temp.detectorsOriginal = rawdatafiles.rawdatafirstcount 
' This throws run time error 424: Object Required

End Sub

我目前的cMetadata类如下:

Private pLabjobName As String
Private pDetectorsOriginal As Collection
Private pDetectorsRecheck As Collection

Private Sub class_initialize()
    Set pDetectorsOriginal = New Collection
    Set pDetectorsRecheck = New Collection
End Sub

Public Property Get labjobName() As String
    labjobName = pLabjobName
End Property

Public Property Let labjobName(fileName As String)
    Dim FSO As New FileSystemObject
    pLabjobName = FSO.GetBaseName(fileName)
    Set FSO = Nothing
End Property

Public Property Get detectorsOriginal() As Collection
    detectorsOriginal = pDetectorsOriginal
End Property

Public Property Set detectorsOriginal(originalFilepath As Collection)
    pDetectorsOriginal = getDetectors(rawdatafiles.rawdatafirstcount)
End Property

当我单步执行代码时,它开始读取"公共属性get rawdatafirstcount()as string" " End Property"之后抛出错误并指回" temp.detectorsOriginal = rawdatafiles.rawdatafirstcount"初始化子行中的行。

我认为我至少关闭了因为temp.labjobName = rawdatafiles.labjobFile代码正确执行。我试过玩数据类型,因为这是一个由字符串分配的集合,但我不出所料地得到数据类型错误,似乎无法弄清楚如何继续。

如果一切按照我想要的方式工作,下面的函数将从rawdatafiles.rawdatafirstcount属性中获取文件路径字符串,并为我返回一个包含探测器名称作为字符串且没有重复项的集合(我不会这样做)知道这个函数是否完全按照我想要的方式工作,因为我还没有能够获得我想在初始子中正确解析的文件路径;但是我可以稍后处理它!):

Function getDetectors(filePath As String) As Collection
Dim i As Integer
Dim detectorsCollection As Collection
Dim OriginalRawData As Workbook

Set OriginalRawData = Workbooks.Open(fileName:=filePath, ReadOnly:=True)
Set detectorsCollection = New Collection

For i = 1 To OriginalRawData.Worksheets(1).Range("D" & Rows.Count).End(xlUp).Row
    detectorsCollection.Add OriginalRawData.Worksheets(1).Cells(i, 4).value, CStr(OriginalRawData.Worksheets(1).Cells(i, 4).value)
    On Error GoTo 0
Next i
getDetectors = detectorsCollection

Set detectorsCollection = Nothing
Set OriginalRawData = Nothing

End Function

再次感谢阅读和您提供的任何帮助!

3 个答案:

答案 0 :(得分:1)

可能不是您的问题,但您在Set设置/获取方法中遗漏了detectorsOriginal

Public Property Get detectorsOriginal() As Collection
    Set detectorsOriginal = pDetectorsOriginal
End Property

Public Property Set detectorsOriginal(originalFilepath As Collection)
    Set pDetectorsOriginal = getDetectors(rawdatafiles.rawdatafirstcount)
End Property

答案 1 :(得分:1)

temp.detectorsOriginal = rawdatafiles.rawdatafirstcount 
' This throws run time error 424: Object Required

它会抛出错误,因为正如其他人已经说过的那样,Set关键字丢失了。

现在开始,Set关键字您想要的内容。实际上,在该作业前面加上Set关键字只会给您带来另一个错误。

让我们看一下你要调用的这个属性:

Public Property Get detectorsOriginal() As Collection
    detectorsOriginal = pDetectorsOriginal
End Property

Public Property Set detectorsOriginal(originalFilepath As Collection)
    pDetectorsOriginal = getDetectors(rawdatafiles.rawdatafirstcount)
End Property

您正在尝试为detectorsOriginal分配一些String值,该值存在于您正在显示的该表单上的某个TextBox控件中 - 但是属性的类型是Collection,这是一种对象类型 - 而且不是String

现在查看 工作的属性:

Public Property Get labjobName() As String
    labjobName = pLabjobName
End Property

Public Property Let labjobName(fileName As String)
    Dim FSO As New FileSystemObject
    pLabjobName = FSO.GetBaseName(fileName)
    Set FSO = Nothing
End Property

这是一个String属性,Property Let mutator使用它给出的fileName参数。

破碎的人:

Public Property Set detectorsOriginal(originalFilepath As Collection)
    pDetectorsOriginal = getDetectors(rawdatafiles.rawdatafirstcount)
End Property

是一个Set mutator,是一个Collection参数,并且没有使用它给出的originalFilepath参数!

这就是我对你的意图感到困惑的地方:除了类型(String)之外,你还传递了Collection的所有外观 - 调用代码想给它一个String

换句话说,调用代码期望这样:

Public Property Let detectorsOriginal(ByVal originalFilepath As String)

看,我不知道你打算在这里做什么;您似乎错过了一些pOriginalFilepath As String私有字段,然后detectorsOriginal将是一些返回某些集合的get-only属性:

Private pOriginalFilePath As String

Public Property Get OriginalFilePath() As String
    OriginalFilePath = pOriginalFilePath
End Property

Public Property Let OriginalFilePath(ByVal value As String)
    pOriginalFilePath = value
End Property

我不知道你想要实现的目标,但我可以告诉你:

  • 不要让Property Set成员忽略其参数,这是一个非常令人困惑的代码。
  • 不要让PropertyGet/Let/Set)成员做任何非平凡的事情。如果它不是简单的并且具有大于零的机会抛出错误,那么它可能不应该是属性。如果需要返回值,请将其设为方法(SubFunction

关于这一点:

Dim FSO As New FileSystemObject
pLabjobName = FSO.GetBaseName(fileName)
Set FSO = Nothing

每当Dim As New {V}}时,VBA会自动实例化该对象。换句话说,这不会抛出任何错误:

Dim FSO As New FileSystemObject
Set FSO = Nothing
pLabjobName = FSO.GetBaseName(fileName)

如果可以,请避免使用As New。在这种情况下,您甚至不需要局部变量 - 请改用With块:

With New FileSystemObject
    pLabjobName = .GetBaseName(fileName)
End With

答案 2 :(得分:0)

So the error is one I've made a time or two (or more). Whenever you assign an object to another object, you have to use the Set reserved word to assign the reference to the Object.

In your code do the following:

In Sub setup()

Set temp.detectorsOriginal = rawdatafiles.rawdatafirstcount

And in the cMetadata class change the Public Property Set detectorsOriginal(originalFilepath As Collection) property to the following:

Public Property Get detectorsOriginal() As Collection
   Set detectorsOriginal = pDetectorsOriginal
End Property

Public Property Set detectorsOriginal(originalFilepath As Collection)
    Set pDetectorsOriginal = getDetectors(rawdatafiles.rawdatafirstcount)
End Property

Also in your function Function getDetectors(filePath as String) as Collection change the statement afterNext i` to

Set getDetectors = detectorsCollection

Also, I'm very glad to hear that you've learned how to use VBA.

When you're ready to create your own Custom Collections, check out this post. Your own custom Collections.

I also book marked Paul Kelly's Excel Macro Mastery VBA Class Modules – The Ultimate Guide as well as his Excel VBA Dictionary – A Complete Guide.

If you haven't been to Chip Pearson's site you should do so. He has a ton of useful code that will help your delivery your projects more quickly.

Happy Coding.