Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在VBA中将ProgressBar用户窗体显示为模态还是非模态更好?_Vba_Modal Dialog_Userform_Modeless_Progress Indicator - Fatal编程技术网

在VBA中将ProgressBar用户窗体显示为模态还是非模态更好?

在VBA中将ProgressBar用户窗体显示为模态还是非模态更好?,vba,modal-dialog,userform,modeless,progress-indicator,Vba,Modal Dialog,Userform,Modeless,Progress Indicator,在VBA中将ProgressBar用户窗体显示为模态还是非模态更好?在VBA中制定进度指标的最佳实践是什么 无模式用户表单需要使用Application.Interactive=False,而模式用户表单本质上阻止与应用程序的任何交互,直到核心过程完成或取消 但是,如果使用了Application.Interactive=False,Esc键会中断代码执行,因此在用户窗体和调用过程中都需要使用Application.enableCanceKey=xlErrorHandler和错误处理(Err.N

在VBA中将ProgressBar用户窗体显示为模态还是非模态更好?在VBA中制定进度指标的最佳实践是什么

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

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

资源密集型调用过程还可能导致无模式用户窗体中的
CommandButton\u Click
UserForm\u Activate
事件发生错误

一般来说,使用模态用户表单的进度指示器似乎更简单,因为正在执行的代码完全包含在用户表单模块中,并且不需要传递变量

但是,将模态UserForms用于进度指示器的问题是,每个需要进度指示器的过程都需要一个单独的UserForm模块,因为调用过程必须位于UserForm\u Activate过程内部

因此,虽然在无模式用户表单中可以有一个可重用的进度指示器,但它的可靠性不如在多模式用户表单中执行代码

哪条路更好


谢谢

还有第三种方法,使用
应用程序.StatusBar

您甚至可以使用U+25A0和U+25A1字符序列来模拟一个真正的进度条。

我将结束这一部分,并说Modal是赢家。我已经尝试了这两种方法,但您最终试图用无模式用户表单来填补太多的漏洞。模态更难,因为它更严格,但它鼓励您将代码分成更小的块,这从长远来看会更好。

绝对是模态的。
如果你要考虑非模态,你应该在分离的进程线程上运行它,而不是在Excel。EXE主线程上。

< P>我认为最初的主题是值得回答的,因为问题很好地被谷歌最先发现。 第1节-理论 首先要说的是,在模块之间传递变量一点也不困难

您需要做的唯一一件事是创建一个单独的模块,并将所有全局变量放在那里。然后你就可以在任何地方阅读所有表格、表格、模块

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

  • 执行most例程过程的函数不位于UserForm模块中
  • 你可以在任何地方和任何地方调用带有进度条的窗口
  • 例程函数/过程之间的唯一连接是全局变量
  • 这是一个很大的优势,在这里是多才多艺的

    第2节-实践 1) 使用全局变量创建模块“声明”:

    作为整数的公共StopForce '此变量将用作用户按下取消按钮的指示器

    公共PCT作为单一 “这是已完成工作的百分比

    作为字符串的公共CurrentFile '要传递到窗体的任何其他参数

    2) 使用按钮创建表单。在按钮的OnClick事件中,应该有一个代码,我们在声明模块中引用全局变量StopForce

    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
    

    事实上,您有以下属性,根据您的需要产生利弊:

    Type      | Impact on UI | Impact on caller execution
    ----------|--------------|-----------------------------
    Modal     | Blocked      | Blocked until Form is closed
    Modeless  | Not blocked  | Continues
    

    如果要阻止UI并让调用方继续,则需要使用
    应用程序以模式模式打开表单。OnTime

    感谢GSerg的建议,但我过去曾尝试过使用该方法,但Excel 2007停止更新窗口并显示“无响应”在应用程序窗口的顶部。我对office 2007不是很有经验,但是如果在将值设置为
    状态栏后立即调用DoEvents会怎么样?嗯,这很有效。哇,这是个不错的选择,不是吗!谢谢你,格斯伯格!使用状态栏作为进度指示器的一个问题是无法提供取消按钮。这项技术不错,但它并不能真正回答关于模态/非模态的最佳实践问题,在ausing statusbar上有一个技术答案。请注意,无模式用户表单在Mac OSI上似乎根本不起作用。在试图通过
    应用程序打开表单时,会收到一条错误消息。OnTime
    (我尝试了不同的变体)。你用什么语法来解释这个?
    Type      | Impact on UI | Impact on caller execution
    ----------|--------------|-----------------------------
    Modal     | Blocked      | Blocked until Form is closed
    Modeless  | Not blocked  | Continues