显示依赖于变量的备用用户窗体
Display alternate UserForm dependent on variable
我想显示依赖于 UserName 环境变量的特定用户窗体。我在整个代码的不同地方更新了用户窗体,所以我认为创建两个独立的用户窗体(具有截然不同的设计)然后在代码。我显然在这里误解了一些东西,因为当它到达 .Show 命令时,VBA 错误:
Dim usrForm As UserForm
If Environ("UserName") = "redacted" Then
Set usrForm = LlamaForm 'for specific user, form styled differently including picture of Llama
Else
Set usrForm = NormalForm 'for EVERYONE ELSE, normal professional looking form
End If
With usrForm 'initialize UserForm and display wait message
.Cancelbutton.Visible = False
.Proceedbutton.Visible = False
.Exitbutton.Visible = False
.labmsg.Caption = Chr(10) & Chr(10) & Chr(10) & "Starting background processes, please wait..."
.Show vbModeless
End With
我是不是把它弄得太复杂了?我真的希望在开始时只更改引用的表单对象,而不是每次需要更新用户时都引入带有冗余代码的逻辑。任何想法或改进将不胜感激。需要注意的是,因为它们截然不同 layout/design,我 真的 喜欢保留两个单独的用户表单而不是操纵一个用户表单(我知道可以做到,但那是与理解为什么我的上述方法不起作用相比,此时需要做更多的工作。)
您可以使用通用对象,但您失去了早期绑定功能
试试这个代码
Option Explicit
Public Sub ShowUserForm()
' You can use a generic object, but you lose the early binding features
Dim myUserForm As Object
If Environ("UserName") = "redacted" Then
Set myUserForm = New LlamaForm
Else
Set myUserForm = New NormalForm
End If
myUserForm.Show
End Sub
如果有效请告诉我
问题是负责显示表单的代码不应该关心任一表单上的任何控件。
出现错误 438,因为 UserForm
class 没有 CancelButton
、ProceedButton
、ExitButton
或 labmsg
成员。
解决方案是 这些成员调用,使它们都反对 Object
(或 Variant
,但 Object
在这里更合适)。 ..或重新评估谁负责什么。
看起来你正在制作某种东西 progress indicator;当您开始需要可交换的对象组件时并且必须保持早期绑定,为此使用的正确工具是多态性,即接口。
链接的文章描述了如何制作一个可重用进度指示器,其工作代码与指示器表单完全分离。你需要的是类似的东西,除了文章末尾提到的你会想要 ProgressIndicatorForm
和 LlamaIndicatorForm
来实现一些 IProgressView
接口,并将此 IProgressView
作为 ProgressIndicator
class 的依赖项,而不是将其硬连接到初始化代码中。
困难的部分是设法在界面上公开进度指示器事件 - 这将需要正式的 ProgressIndicatorEvents
class 来转发 Activated
和 Cancelled
事件到 ProgressIndicator
class,类似于 this class 将事件从抽象视图转发到另一个组件。
做对了,你最终得到的调用代码如下所示:
Dim progressForm As IProgressView
If Environ$("username") = "redacted" Then
Set progressForm = New LlamaProgressForm
Else
Set progressForm = New StandardProgressForm
End If
With ProgressIndicator.Create("DoWork", Form:=progressForm)
.Execute
End With
其中 DoWork
是您的 "worker code" - 可以是采用 ProgressIndicator
参数的任何 Sub
过程。
显然,这比仅针对 Object
编码要多得多,我不会责怪您采用简单的方法。但是如果学习新的编程概念比仅仅让它工作更重要的话,这里的原则非常值得研究。
我想显示依赖于 UserName 环境变量的特定用户窗体。我在整个代码的不同地方更新了用户窗体,所以我认为创建两个独立的用户窗体(具有截然不同的设计)然后在代码。我显然在这里误解了一些东西,因为当它到达 .Show 命令时,VBA 错误:
Dim usrForm As UserForm
If Environ("UserName") = "redacted" Then
Set usrForm = LlamaForm 'for specific user, form styled differently including picture of Llama
Else
Set usrForm = NormalForm 'for EVERYONE ELSE, normal professional looking form
End If
With usrForm 'initialize UserForm and display wait message
.Cancelbutton.Visible = False
.Proceedbutton.Visible = False
.Exitbutton.Visible = False
.labmsg.Caption = Chr(10) & Chr(10) & Chr(10) & "Starting background processes, please wait..."
.Show vbModeless
End With
我是不是把它弄得太复杂了?我真的希望在开始时只更改引用的表单对象,而不是每次需要更新用户时都引入带有冗余代码的逻辑。任何想法或改进将不胜感激。需要注意的是,因为它们截然不同 layout/design,我 真的 喜欢保留两个单独的用户表单而不是操纵一个用户表单(我知道可以做到,但那是与理解为什么我的上述方法不起作用相比,此时需要做更多的工作。)
您可以使用通用对象,但您失去了早期绑定功能
试试这个代码
Option Explicit
Public Sub ShowUserForm()
' You can use a generic object, but you lose the early binding features
Dim myUserForm As Object
If Environ("UserName") = "redacted" Then
Set myUserForm = New LlamaForm
Else
Set myUserForm = New NormalForm
End If
myUserForm.Show
End Sub
如果有效请告诉我
问题是负责显示表单的代码不应该关心任一表单上的任何控件。
出现错误 438,因为 UserForm
class 没有 CancelButton
、ProceedButton
、ExitButton
或 labmsg
成员。
解决方案是 Object
(或 Variant
,但 Object
在这里更合适)。 ..或重新评估谁负责什么。
看起来你正在制作某种东西 progress indicator;当您开始需要可交换的对象组件时并且必须保持早期绑定,为此使用的正确工具是多态性,即接口。
链接的文章描述了如何制作一个可重用进度指示器,其工作代码与指示器表单完全分离。你需要的是类似的东西,除了文章末尾提到的你会想要 ProgressIndicatorForm
和 LlamaIndicatorForm
来实现一些 IProgressView
接口,并将此 IProgressView
作为 ProgressIndicator
class 的依赖项,而不是将其硬连接到初始化代码中。
困难的部分是设法在界面上公开进度指示器事件 - 这将需要正式的 ProgressIndicatorEvents
class 来转发 Activated
和 Cancelled
事件到 ProgressIndicator
class,类似于 this class 将事件从抽象视图转发到另一个组件。
做对了,你最终得到的调用代码如下所示:
Dim progressForm As IProgressView
If Environ$("username") = "redacted" Then
Set progressForm = New LlamaProgressForm
Else
Set progressForm = New StandardProgressForm
End If
With ProgressIndicator.Create("DoWork", Form:=progressForm)
.Execute
End With
其中 DoWork
是您的 "worker code" - 可以是采用 ProgressIndicator
参数的任何 Sub
过程。
显然,这比仅针对 Object
编码要多得多,我不会责怪您采用简单的方法。但是如果学习新的编程概念比仅仅让它工作更重要的话,这里的原则非常值得研究。