2010-01-30 32 views
8

将VBA中的ProgressBar用户窗体显示为模态或无模式会更好吗?在VBA中开发进度指标的最佳实践是什么?将VBA中的ProgressBar用户窗体显示为模态或无模式会更好吗?

无模式用户窗体需要使用Application.Interactive = False,而模态用户窗体本质上阻止与应用程序的任何交互,直到核心过程完成或被取消。

但是,如果使用Application.Interactive = False,则Esc键会中断代码执行,因此在用户窗体和调用过程中都需要使用Application.EnableCancelKey = xlErrorHandler和错误处理(Err.Number = 18)。

资源密集型调用过程也可能导致CommandButton_ClickUserForm_Activate事件在无模式用户窗体中失火。

通常,使用模式用户窗体的进度指示器看起来更简单,因为正在执行的代码完全包含在用户窗体模块中,并且不需要传递变量。

但是,使用用于进度指示器的模式UserForms的问题在于,需要进度指示器的每个过程都需要单独的UserForm模块,因为调用过程必须位于UserForm_Activate过程中。

因此,虽然在无模式UserForm中可能有单个可重用的进度指示器,但它将比从多个模式用户窗体中执行代码的可靠性要低。

哪种方式更好?

谢谢!

回答

1

我打算关闭这一个,说莫代尔是赢家。我已经尝试了两种方式,但最终你会试图通过无模式的用户表单来关闭太多的漏洞。莫代尔更加困难,因为它更严格,但它鼓励你将代码分解成更小的块,无论如何,从长远来看这更好。

3

还有第三种方法,使用Application.StatusBar。 您甚至可以使用U + 25A0和U + 25A1字符序列模拟真正的进度条。

+0

谢谢GSerg的建议,但我曾尝试过使用它,但Excel 2007停止更新窗口并在应用程序窗口顶部显示“Not Responding”。 – Kuyenda 2010-01-31 00:41:27

+2

我对office 2007不太了解,但是如果你在给'StatusBar'设置一个值之后立即调用DoEvents呢? – GSerg 2010-01-31 01:09:32

+0

嗯,那工作。哇,这是一个不错的选择是不是!谢谢GSerg! – Kuyenda 2010-01-31 01:23:17

1

绝对模态。 如果你打算考虑Modeless,你应该在一个单独的进程外线程上运行它,而不是在Excel.exe主线程上。

1

我认为最初的话题值得回复,因为问题的表述非常好,谷歌首先发现它。

第1 - 理论

的第一件事要说的是,在模块之间传递变量是不难的。

你需要做的唯一的事情就是创建一个单独的模块,并把所有的全局变量。然后你将能够以各种形式,表单,模块阅读它们。

第二件事是窗口应该是MODELESS。为什么? 答案是保持代码的流动性,即

  1. 其中执行最常规的过程不位于用户窗体模块中的功能
  2. 可以调用带进度条的窗口来自世界各地和
  3. 常规功能/程序之间的唯一联系是全局变量

这是一个很大的优势是多功能这里。

第2部分 - 实践

1)创建模块“申报”与全局变量:

公共StopForce作为整数 “这个变量将被用作一个指标,该用户按下的取消按钮

公共PCTDone单 “这是已经做

P中的工作% ublic CurrentFile As String '我们想要传递给表单的任何其他参数。

2)用按钮创建表单。在按钮的OnClick事件应该有,我们指的是全局变量StopForce宣言模块

Private Sub CommandButton1_Click() 

Declaration.StopForce = 1 
    End Sub 

3)添加一个程序代码,您更新进度条

Sub UpdateProgressBar(PCTDone_in As Single) 
With UserForm1 
    ' Update the Caption property of the Frame control. 
    .FrameProgress.Caption = Format(PCTDone_in, "0%") 
    ' Widen the Label control. 
    .LabelProgress.Width = PCTDone_in * _ 
     (.FrameProgress.Width) 
    ' Display the current file from global variable 
    .Label1.Caption = Declaration.CurrentFile 
End With 
End Sub 

4)在任何其他模块中,我们必须具有执行例行程序的功能或程序/子程序:

For i=1 to All_Files 

Declaration.CurrentFile = myFiles (i) 

FormFnc.UpdateProgressBar (i/.Range("C11").Value) 


DoEvents 

If Declaration.StopForce = 1 Then 
    GoTo 3 
End If 

Next i 
+0

请注意,无模式UserForms在Mac OS上看起来完全不起作用 – 2017-05-30 06:04:35

相关问题