我有一个名为 cMilestones 的类,我有多个属性集,有些是Date
,有些是Integer
,有些是String
。
问题/挑战:我遇到困难,我想使用Let
和Get Property
语句,但要使用已经定义的类属性(称为 CommittedDate 和 UncommittedDate )。
PlanDate 财产条件:
If IsDate(CommittedDate) Then PlanDate = CommittedDate
If IsDate(UnCommittedDate) Then PlanDate = UnCommittedDate
到目前为止,我的 c里程碑类代码(工作部分)......
Private pMilestoneName As String
Private pCommittedDate As Date
Private pUncommittedDate As Date
Private pPlanDate As Date
Private pmsRow As Integer
Private pmsRowPlan As Integer
Private pmsRowAct As Integer
Private pmsHgt_Up As Single
Private pmsHgt_Down As Single
' --- Get/Let Methods ---
Public Property Get MilestoneName() As String
MilestoneName = pMilestoneName
End Property
Public Property Let MilestoneName(value As String)
pMilestoneName = value
End Property
Public Property Get CommittedDate() As Date
CommittedDate = pCommittedDate
End Property
Public Property Let CommittedDate(value As Date)
If IsDate(value) Then
pCommittedDate = value
End If
End Property
Public Property Get UncommittedDate() As Date
UncommittedDate = pUncommittedDate
End Property
Public Property Let UncommittedDate(value As Date)
If IsDate(value) Then
pUncommittedDate = value
End If
End Property
还没有工作......
' ****** This is where I am not able to make it work *******
Public Property Get PlanDate(pCommittedDate As Date) As Date
PlanDate = pPlanDate
End Property
' ****** This is where I am not able to make it work *******
Public Property Let PlanDate(pCommittedDate As Date, pUncommittedDate As Date)
'Public Sub PlanDate(pCommittedDate As Date, pUncommittedDate As Date)
If IsDate(pCommittedDate) Then
pPlanDate = pCommittedDate
Else
If IsDate(pUncommittedDate) Then
pPlanDate = pUncommittedDate
Else
' Milestone doesn't have Committed or Uncommitted plan >> raise Error Flag
End If
End If
End Property
这是我的 Sub ,我使用数组来存储使用类对象的很多里程碑:
Public Sub ReadMilestonesRange_toClass()
i = 0
DataRow = FirstRow
LastExistingMSRow = DataRow
' loop through all milestones in Column A to find the latest Row that has Milestone Name in it
While DataRow <= LastMSRow
Set ProjMilestones = New cMilestones
ProjMilestones.MilestoneName = Cells(DataRow, 1)
ProjMilestones.MSRow = DataRow
ProjMilestones.CommittedDate = Cells(DataRow, 2)
ProjMilestones.UncommittedDate = Cells(DataRow, 3)
' ****** Want to add the PlanDate to my cMilestones Class array ******
ProjMilestones.PlanDate (ProjMilestones.UncommittedDate)
ProjMilestones.ForecastDate = Cells(DataRow, 4)
ProjMilestones.ActualDate = Cells(DataRow, 5)
If ProjMilestones.MilestoneName <> "" Then
ReDim Preserve ProjArrMilestones(0 To i)
Set ProjArrMilestones(i) = ProjMilestones
i = i + 1
LastExistingMSRow = DataRow
End If
Set ProjMilestones = Nothing
DataRow = DataRow + 1
Wend
MilestonesNum = LastExistingMSRow - FirstRow + 1 ' Total of Milestones in Milestone Table
Set ProjMilestones = Nothing
End Sub
答案 0 :(得分:1)
pCommittedDate
和pUncommittedDate
是类字段,因此它们在任何类实例中都可用,因此您不希望将它们作为参数传递给Property Get PlanDate()
和{{1方法。
因此,您只需要针对Property Let PlanDate()
值检查它们以查看是否已初始化
所以这样的代码:
0
这样您的代码就会运行,但Public Property Get PlanDate() As Date
PlanDate = pPlanDate
End Property
Public Property Let PlanDate(value As Date)
If pCommittedDate <> 0 Then 'if pCommittedDate is already "initialized"
pPlanDate = pCommittedDate
Else
If pUncommittedDate <> 0 Then 'if pUncommittedDate is already "initialized"
pPlanDate = pUncommittedDate
Else
' Milestone doesn't have Committed or Uncommitted plan >> raise Error Flag
End If
End If
End Property
是一个非常奇怪的属性,因为它的PlanDate
访问器需要一个Let
而根本没用!“ / p>
由于您似乎不希望类消费者设置value
,只需将其转换为普通类字段:
PlanDate
在那里你摆脱了所有那些Public PlanDate As Date
'...
Public Property Get CommittedDate() As Date
CommittedDate = pCommittedDate
End Property
Public Property Let CommittedDate(value As Date)
pCommittedDate = value
PlanDate = pCommittedDate '<--| set PlanDate as well
End Property
Public Property Get UncommittedDate() As Date
UncommittedDate = pUncommittedDate
End Property
Public Property Let UncommittedDate(value As Date)
pUncommittedDate = value
If pCommittedDate = 0 Then PlanDate = pUncommittedDate '<--| set PlanDate only if 'pCommittedDate' is not initialized (changed pPlanDate to PlanDate)
End Property
,因为你已经声明IsDate(value)
所以在类消费者代码中无论如何都会发生错误,如果它试图设置任何value as Date
值无效的
这里有一个可能的利用类,如上面的最后一个代码
Date
所以问题是:是否真的有必要让类消费者设置Sub main()
Dim myvar As New cMilestones
With myvar
.CommittedDate = "1/1/2015" '<--| this will define 'PlanDate' as well
.UncommittedDate = "31/12/2105" '<--| this will NOT redefine 'PlanDate', since 'CommittedDate' is already defined
.PlanDate = "1/1/2016" '<--| this will redefine 'PlanDate'...
End With
End Sub
?
答案 1 :(得分:1)
如果需要使用数组将多个值传递给Property。
milestone.PlanDate = Arrray(#1/1/2016#, #2/1/2016#)
或
milestone.PlanDate = Range("A1:B1").Value
Public Property Let PlanDate(arrDates() As Variant)
If IsDate(arrDates(0)) Then
pPlanDate = arrDates(0)
Else
If IsDate(arrDates(1)) Then
pPlanDate = arrDates(1)
Else
' Milestone doesn't have Committed or Uncommitted plan >> raise Error Flag
End If
End If
End Property
答案 2 :(得分:0)
在PlanDate的访问器中,你需要一个参数pCommitedDate - 但是你没有在你的身体中使用这个变量 - 因为它与解析这个参数完全无关。
Public Property Get PlanDate(pCommittedDate As Date) As Date
PlanDate = pPlanDate
End Property
如果您想将pPlanDate分配到CommittedDate
或UnCommittedDate
,只需将其添加到您的身体即可轻松完成此操作。
对于修饰符,请尝试使用Debug.Print输出来检查输入变量值。无论如何,你可以修改你的代码:
Public Property Let PlanDate(pCommittedDate As Date, pUncommittedDate As Date)
If IsDate(pCommittedDate) Then
pPlanDate = pCommittedDate
ElseIf IsDate(pUncommittedDate) Then
pPlanDate = pUncommittedDate
Else
' Print to immediate-window
Debug.Print "pCommittedDate or pUncommittedDate failed"
End If
End Property
答案 3 :(得分:0)
好的,让我们首先处理Rory非常有效的观点:
如果将变量声明为Date
,则测试IsDate(var)
将始终返回True
,因为在初始化变量时会分配日期值。试试这段代码来证明:
Dim dat As Date
Debug.Print dat
Debug.Print IsDate(dat)
输出将是:
早上12点00分
真
当属性收到值时,有几种方法可以标记,也许最简单的方法就是设置一个布尔标志。像这样:
Private pDate1 As Date
Private pDate1IsSet As Boolean
Public Property Let Date1(val As Date)
pDate1 = val
pDate1IsSet = True
End Property
如果您运行以下模块代码
Dim oSchedule As clsSchedule
Set oSchedule = New clsSchedule
Debug.Print oSchedule.Date1IsSet & " " & oSchedule.Date1
oSchedule.Date1 = #1/21/2014#
Debug.Print oSchedule.Date1IsSet & " " & oSchedule.Date1
然后输出将是:
错误12:00:00 am。
True 21/01/2014
但是,在您的情况下,在其他两个日期设置器中设置pPlanDate
变量可能更简单,如下所示:
Private pDate1 As Date
Private pDate2 As Date
Private pTheDate As Date
Public Property Let Date1(val As Date)
pDate1 = val
pTheDate = val
End Property
Public Property Let Date2(val As Date)
pDate2 = val
pTheDate = val
End Property
Public Property Get TheDate() As Date
TheDate = pTheDate
End Property
最后,如果你确实需要测试是否没有设置日期,那么也许这应该是你班级的属性。您甚至可以优先考虑所需的日期,如下所示:
Private pDate1 As Date
Private pDate2 As Date
Private pTheDate As Date
Private pDateIsSet As Boolean
Public Property Let Date1(val As Date)
pDate1 = val
pTheDate = val
pDateIsSet = True
End Property
Public Property Let Date2(val As Date)
pDate2 = val
If Not pDateIsSet Then
pTheDate = val
pDateIsSet = True
End If
End Property
Public Property Get TheDate() As Date
TheDate = pTheDate
End Property
Public Property Get DateIsSet() As Boolean
DateIsSet = pDateIsSet
End Property
在我看来,这使得下面的代码更容易阅读,至少在我看来,它提供了一个包含特定于其目的的属性的类对象。您的课堂设计考虑因素可能会让您深思熟虑?
Dim oSchedule As clsSchedule
Set oSchedule = New clsSchedule
oSchedule.Date1 = #1/21/2014#
If oSchedule.DateIsSet Then
Debug.Print oSchedule.TheDate
Else
Debug.Print "No date"
End If