2017-04-10 81 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;這樣你可以用一個整齊的小驗證/通知標籤來替換煩人的消息框。


這就是說,我不知道你的路徑/文件錯誤來自什麼,你的文章沒有任何文件做任何事情。但這應該可以幫助你至少得到你的表格。

相關問題