我想首先感谢大家在过去几个月中给予我的帮助!我已经从不知道如何访问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
再次感谢阅读和您提供的任何帮助!
答案 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
成员忽略其参数,这是一个非常令人困惑的代码。Property
(Get/Let/Set
)成员做任何非平凡的事情。如果它不是简单的并且具有大于零的机会抛出错误,那么它可能不应该是属性。如果需要返回值,请将其设为方法(Sub
或Function
。关于这一点:
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 after
Next 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.