当宏在另一个工作簿中运行时,如何打开工作簿?

时间:2019-02-08 17:31:14

标签: excel vba

我遇到了一个问题,我创建了一个VBA计时器,该计时器从指定时间倒数到零。这个宏运行了一段时间,因此,当我尝试打开另一个工作簿时,什么也没发生,就像宏阻止另一个工作簿打开一样?

我的计时器子

Private Sub Timer15_main(play As Boolean)
 Dim UserInput As String

    If play Then
      UserInput = TextBox1.Value 'this is what the user inputs and how long the timer should run
     Else
      timer_15_pause_button = False
      UserInput = "00:15:00" 'this is what the user inputs and how long the timer should run
    End If

        'validate userinput und ensure hh:mm:ss format
        Select Case Len(UserInput) - Len(Replace$(UserInput, ":", ""))
            Case 2 'input format is hh:mm:ss

            Case 1 'input format is mm:ss
                UserInput = "00:" & UserInput
            Case 0 'input format is ss
                UserInput = "00:00:" & UserInput
            Case Else
                MsgBox "invalid input"
                Exit Sub
        End Select

        'we need to convert the string UserInput into a double and
        'convert it into seconds (Timer uses seconds!)
        Dim SecondsToRun As Long
        SecondsToRun = CDbl(TimeValue(UserInput)) * 24 * 60 * 60
         TextBox4.Value = Format$((SecondsToRun / 24 / 60 / 60) + Time(), "hh:mm:ss")
        Dim TimerStart As Double
        TimerStart = Timer 'remember when timer starts

        Do

             If SecondsToRun - (Timer - TimerStart) < 10 Then
             TextBox1.BackColor = RGB(255, 0, 0)
            End If

            TextBox1.Value = Format$((SecondsToRun - (Timer - TimerStart)) / 24 / 60 / 60, "hh:mm:ss")
            'count backwards from 01:15 format as hh:mm:ss

            DoEvents
            If timer_15_pause_button = True Then
            Exit Sub
            End If


        Loop While TimerStart + SecondsToRun > Timer 'run until SecondsToRun are over
        TextBox1.BackColor = RGB(255, 255, 255)

        'TextBox4.Value = ""

        End Sub

1 个答案:

答案 0 :(得分:2)

假设表单显示如下:

UserForm1.Show
DoSomething

然后,该表单为 modal ,这意味着DoSomething调用将在表单关闭后才会运行。显示模式表格时,它控制消息循环,并且主机应用程序始终不可用:用户唯一可以与之交互的就是表格。

如果表单显示如下:

UserForm1.Show vbModeless
DoSomething

然后显示该表单,并立即运行DoSomething调用;用户仍然可以与主机应用程序进行交互,并且表单中的代码可以异步运行。

但是这样的循环:

Do
    ' do stuff
    DoEvents
Loop While {condition}

设计错误:如果没有DoEvents,循环将完全劫持消息循环,模态或无模态不会产生任何影响,并且主机应用程序可能会一直“(不响应)”,直到循环完成。 使用DoEvents ,这是一个繁忙的循环,不断告诉Windows“嘿,您有什么要运行的吗?那就继续!” -您要做的是注册一个程序,该程序将每秒调用一次以更新表单上的计时器标签。

该过程必须在单独的标准模块中-理想情况下,该模块要与显示表单的模块相同,并且理想情况下应处理该表单的同一实例。

Option Explicit
Private theForm As UserForm1

Public Sub ShowTheForm()
    If theForm Is Nothing Then Set theForm = New UserForm1
    theForm.Show vbModeless
End Sub

Public Sub OnTimerTick()
    If theForm Is Nothing Then Exit Sub
    theForm.HandleTimerTick
End Sub

现在,表单需要公开HandleTimerTick过程,并安排OnTimerTick宏。因此,您可能有一个CommandButton控件,单击该控件即可开始计划循环:

Dim TimerStart As Double

Private Sub CommandButton1_Click()
    ' validate inputs...
    TimerStart = Timer
    Application.OnTime Now + TimeValue("00:00:01"), "OnTimerTick"
End Sub

Public Sub HandleTimerTick()
    'timer has ticked, we're at least 1 second later.
    Dim secondsElapsed As Double
    secondsElapsed = Timer - TimerStart

    'update the textbox accordingly...
    TextBox1.Text = Format$(secondsToRun - secondsElapsed, "hh:mm:ss")

    'now determine if we need to schedule another tick:
    If Int(secondsToRun - secondsElapsed) > 0 Then
        Application.OnTime Now + TimeValue("00:00:01"), "OnTimerTick"
    End If
End Sub

请注意,不再有显式循环,也没有DoEvents:只是一个计划的宏,它告诉形式“嘿,打勾!”表格会通过更新自身进行响应,并在需要时重新安排另一个刻度。