2017-04-10 84 views
0
Private cancel As Boolean 


Public Function ShowDatesDialog(startDate As Date, endDate As Date, timeInterval As String) As Boolean 

Call Initialize 

Me.Show 

If Not cancel Then 

    startDate = calStartDate.Value 
    endDate = calEndDate.Value 
    Select Case True 
     Case optMonth: timeInterval = "m" 
     Case optWeek: timeInterval = "w" 
     Case optDay: timeInterval = "d" 
    End Select 
End If 
ShowDatesDialog = Not cancel 

Unload Me 

End Function 

Private Sub Initialize() 

calStartDate.Value = DateSerial(Year(Date) - 2, Month(Date), Day(Date)) 

calEndDate.Value = Date 

optMonth.Value = True 

End Sub 

Private Function Valid() As Boolean 

Dim startDate As Date, endDate As Date 

Valid = True 

startDate = calStartDate.Value 

endDate = calEndDate.Value 

If startDate >= endDate Then 

    Valid = False 
    MsgBox "The starting date should be before the ending date.", _ 
    vbInformation, "Invalid dates" 
    calStartDate.SetFocus 
    Exit Function 
    ElseIf startDate < EARLIST_DATE Then 
    Valid = False 
    MsgBox " The starting date shouldn't be before 1990.", _ 
    vbInformation, "Start date too early" 
    calStartDate.SetFocus 
    Exit Function 
    ElseIf endDate > Date Then 
    Valid = False 
    masgbox " The ending date shouldn't be after today's date.", _ 
    vbInformation, "end date too late" 
    calEndDate.SetFocus 
    Exit Function 
End If 

End Function 

Private Sub btnOK_Click() 

    If Valid Then Me.Hide 

    cancel = False 

End Sub 

Private Sub btnCancel_Click() 

Me.Hide 

cancel = True 

End Sub 



Private Sub UserForm_QueryClose(cancel As Integer, CloseMode As Integer) 

    If CloseMode = vbFormControlMenu Then btnCancel_Click 

End Sub 
+0

我可以想象,单击用户窗体时出现错误的唯一方法是在UserForm_Click事件或UserForm_Activate事件中存在代码。你在这些事件中是否有代码? –

回答

0

很多。

InitializebtnCancel_Click是事件处理程序:不应该明确调用它们。他们的目的是为了处理事件

你是在正确的道路上,虽然 - 我看你真的已经很努力避免使用默认实例...但我怀疑你的调用代码看起来是这样的:

MyAwesomeForm.ShowDatesDialog startDate, endDate, timeInterval 

,对吗?

那么这ShowDatesDialog运行关闭窗体的默认实例,这意味着这样的:

Me.Show 

显示的默认实例。

一个表格不应该为自己摧毁负责(因为它不是自己创建的) - 你做得很好Me.Hide,但Unload Me然后击败了它,因为它使对象自毁,这意味着调用者可以永远不要抓住对象:它们显示形式,然后消失,并且在对象做任何事情之前对象已经消失。

表格不应该负责显示本身:这也是来电者的工作。

揭露封装cancel场为只读属性,并将其重命名为cancelled,使其不与QuerClose处理程序的参数冲突:

Private cancelled As Boolean 

Public Property Get IsCancelled() As Boolean 
    IsCancelled = cancelled 
End Property 

暴露你模型为属性太:

Public Property Get StartingDate() As Date 
    StartingDate = calStartDate.Value 
End Property 

Public Property Get EndingDate() As Date 
    EndingDate = calEndDate.Value 
End Property 

Public Property Get TimeInterval() As String 
    Select Case True 
     Case optMonth.Value 
      TimeInterval = "m" 

     Case optWeek.Value 
      TimeInterval = "w" 

     Case optDay.Value 
      TimeInterval = "d" 

     Case Else 
      TimeInterval = vbNullString 
    End Select 
End Property 

现在你的来电可以做到这一点 - 基本上你ShowDatesDialog功能变为调用代码:

With New MyAwesomeForm 
    .Show 
    If Not .IsCancelled Then 

     Dim startDate As Date 
     startDate = .StartingDate 

     Dim endDate As Date 
     endDate = .EndingDate 

     Dim interval As String 
     interval = .TimeInterval 

    End If 
End With 

Valid函数应该是一个动词,例如, Validate开始带有动词,例如, IsValid;因为该功能有副作用,我更倾向于命名它Validate而不是IsValid,但YMMV。其压痕严重需要一些爱,虽然:

If startDate >= endDate Then 

    Valid = False 
    MsgBox "The starting date should be before the ending date.", _ 
    vbInformation, "Invalid dates" 
    calStartDate.SetFocus 
    Exit Function 

ElseIf startDate < EARLIST_DATE Then 

    Valid = False 
    MsgBox " The starting date shouldn't be before 1990.", _ 
    vbInformation, "Start date too early" 
    calStartDate.SetFocus 
    Exit Function 

ElseIf endDate > Date Then 

    Valid = False 
    masgbox " The ending date shouldn't be after today's date.", _ 
    vbInformation, "end date too late" 
    calEndDate.SetFocus 
    Exit Function 

End If 

注意,如果VBA让您无需在编译时抱怨运行这段代码,那么你需要在模块的顶部指定Option Explicit(应该是在顶部的模块),因为这不可能编译:

masgbox " The ending date shouldn't be after today's date.", _ 
    vbInformation, "end date too late" 

除非你有地方规定,当然,一个masgbox功能。考虑通过反转布尔逻辑来减少冗余(布尔变量为False,直到它被分配给True),提取message变量并标题化标题,并且只在一个地方调用MsgBox


需要明确的是,这里是你的窗体的代码隐藏在我看来:

Option Explicit 
Private Const EARLIEST_DATE As Date = #1990-01-01# 
Private cancelled As Boolean 

Public Property Get IsCancelled() As Boolean 
    IsCancelled = cancel 
End Property 

Public Property Get StartingDate() As Date 
    StartingDate = calStartDate.Value 
End Property 

Public Property Get EndingDate() As Date 
    EndingDate = calEndDate.Value 
End Property 

Public Property Get TimeInterval() As String 
    Select Case True 
     Case optMonth.Value 
      TimeInterval = "m" 

     Case optWeek.Value 
      TimeInterval = "w" 

     Case optDay.Value 
      TimeInterval = "d" 

     Case Else 
      TimeInterval = vbNullString 
    End Select 
End Property 

Private Sub Initialize()   
    calStartDate.Value = DateSerial(Year(Date) - 2, Month(Date), Day(Date)) 
    calEndDate.Value = Date 
    optMonth.Value = True   
End Sub 

Private Sub UserForm_QueryClose(cancel As Integer, CloseMode As Integer) 
    If CloseMode = vbFormControlMenu Then 
     cancelled = True 
     Me.Hide 
    End If 
End Sub 

Private Sub btnCancel_Click() 
    cancelled = True 
    Me.Hide 
End Sub 

Private Sub btnOk_Click() 
    If Validate Then Me.Hide 
End Sub 

Private Function Validate() As Boolean 

    Dim result As Boolean 
    Dim message As String 

    If StartingDate >= EndingDate Then 

     message = "Invalid selection. The starting date must be before the ending date.", 
     calStartDate.SetFocus 

    ElseIf StartingDate < EARLIEST_DATE Then 

     message = "Start date is too early. Cannot be before 1990." 
     calStartDate.SetFocus 

    ElseIf EndingDate > Date Then 

     message = "End date is too late. The ending date cannot be after today's date." 
     calEndDate.SetFocus 

    Else 
     result = True 
    End If 

    If Not result Then MsgBox message, "Validation Failed", vbExclamation 
    Validate = result 

End Function 

而且调用代码:

Public Sub DoSomething() 
    With New MyAwesomeForm 

     .Show 
     If Not .IsCancelled Then 

      Dim startDate As Date 
      startDate = .StartingDate 

      Dim endDate As Date 
      endDate = .EndingDate 

      Dim interval As String 
      interval = .TimeInterval 

      '...do stuff... 

     End If 
    End With 
End Sub 

考虑处理calStartDatecalEndDate控制Changed事件来执行更早的验证,并且只有在窗体有效时才启用按钮OK;这样你可以用一个整齐的小验证/通知标签来替换烦人的消息框。


这就是说,我不知道你的路径/文件错误来自什么,你的文章没有任何文件做任何事情。但这应该可以帮助你至少得到你的表格。

相关问题