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
回答
很多。
Initialize
和btnCancel_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
考虑处理calStartDate
和calEndDate
控制Changed
事件来执行更早的验证,并且只有在窗体有效时才启用按钮OK;这样你可以用一个整齐的小验证/通知标签来替换烦人的消息框。
这就是说,我不知道你的路径/文件错误来自什么,你的文章没有任何文件做任何事情。但这应该可以帮助你至少得到你的表格。
- 1. VBA删除用户窗体控制对象,它是离屏
- 2. 错误“无法创建组件‘控件名称’”当拖动Windows窗体用户控件到窗体
- 3. 我的线程没有看到窗体窗体组件
- 4. 如何在我的主窗体中显示处理窗体
- 5. 用户窗体运行时错误'424':需要的对象Excel VBA
- 6. 问题当我在我的窗体上显示Powerpoint的c#.net
- 7. 访问没有窗体实例的VBA用户窗体控件
- 8. Django窗体总是显示错误“此字段是必需的”
- 9. phpMyAdmin错误:我在用户帐户中看到错误
- 10. VBA用户窗体刷新
- 11. 我有一个用户窗体的列表框,但当我显示用户窗体的列表框是空的,但是当我不显示我可以看到项目
- 12. 文本框在用户窗体当我改变ComboBox2价值
- 13. 从窗体内的用户控件,我如何访问父窗体的DataGridView?
- 14. 窗体:错误没有显示错误
- 15. Excel VBA用户窗体显示选中的工作表
- 16. Kohana 3.2,在窗体中显示错误
- 17. Spring Framework .... wat是窗体之间的区别:错误路径和窗体:lable path ...?
- 18. 无法在窗体上看到我的图片 - asp.net
- 19. 账户对象中的SetDefaultAccountValues它显示总和错误
- 20. Django窗体,ModelMultipleChoiceField上的显示错误
- 21. Excel 2010个的用户窗体VBA
- 22. 如何从父窗体调用用户窗体中的方法?
- 23. 使用简单的形式在窗体上显示用户
- 24. 窗体:错误不显示错误列表,但窗体:错误path =“x”工程
- 25. Excel VBA用户窗体 - 设置与用户窗体大小相同的图表
- 26. Django窗体:我如何显示最初的空白窗体?
- 27. 获取拖入Windows窗体窗体的文件的路径
- 28. 用户控制单击 - Windows窗体
- 29. 在窗体外显示弹出窗体错误
- 30. 在用户窗体的文本框中的箭头键,VBA
我可以想象,单击用户窗体时出现错误的唯一方法是在UserForm_Click事件或UserForm_Activate事件中存在代码。你在这些事件中是否有代码? –