Vba Excel中的MsgBox焦点

Vba Excel中的MsgBox焦点,vba,excel,excel-2010,msgbox,Vba,Excel,Excel 2010,Msgbox,我正在用Excel中的VBA计算大量数据,并希望在计算完成后显示MsgBox。MsgBox实际上显示了计算所用的时间 问题是当用户在计算过程中决定做其他事情时。Excel会继续计算,完成后,MsgBox会显示,但由于某些原因,Excel不会将焦点放在MsgBox上。Excel图标将在任务栏中闪烁,如果我们单击它,Excel将最大化,但MsgBox位于Excel窗口后面,我们永远无法单击它。所以唯一的办法就是杀死excel.exe。。。不太好。Alt+Pause也不起作用,因为代码只有在当前代码行

我正在用Excel中的VBA计算大量数据,并希望在计算完成后显示MsgBox。MsgBox实际上显示了计算所用的时间

问题是当用户在计算过程中决定做其他事情时。Excel会继续计算,完成后,MsgBox会显示,但由于某些原因,Excel不会将焦点放在MsgBox上。Excel图标将在任务栏中闪烁,如果我们单击它,Excel将最大化,但MsgBox位于Excel窗口后面,我们永远无法单击它。所以唯一的办法就是杀死excel.exe。。。不太好。Alt+Pause也不起作用,因为代码只有在当前代码行结束后才会停止。。。当MsgBox关闭时

我以前尝试过AppActivate(“Microsoft Excel”)函数,但没有成功()。由于Excel 2010将文档名称添加到窗口标题中,因此应用程序名称实际上比该名称长


你知道我该如何避开这个恼人的问题吗?

听起来宏过程让应用程序没有响应。不确定这是否有帮助,但您是否考虑过在长时间运行的流程中添加DoEvents或Sleep(API调用)以将控制权交还给操作系统?Sleep是一个API调用,因此您需要在模块中声明它才能使用它。 DoEvents阻止应用程序锁定,但它确实使用了更多CPU,因此如果它处于循环I 将每隔一段时间访问一次(30%或更少的迭代)。如果它不是一个循环,并且您知道在长时间运行的流程中瓶颈在哪里,那么您可以在每个长时间运行的流程之后调用DoEvents

#If VBA7 And Win64 Then
' 64 bit Excel
Public Declare PtrSafe Sub Sleep Lib "kernel32" ( _
    ByVal dwMilliseconds As LongLong)
#Else
' 32 bit Excel
Public Declare Sub Sleep Lib "kernel32" ( _
    ByVal dwMilliseconds As Long)
#End If

然后在你的过程中

Sub SomeLongProcessWithDoEventsExample()
   For i = 1 to 100000
       'Some lengthy code
       If i Mod 333 = 0 Then
          DoEvents
       End If
   Next i
End Sub

Sub SomeLongProcessWithSleepExample()
   For i = 1 to 100000
       'Some lengthy code
       If i Mod 333 = 0 Then
          Sleep 1 * 1000 'Millseconds
       End If
   Next i      
End Sub
我建议将Application.ScreenUpdating=False设置为False,然后在流程完成后将其重新打开,但这可能会让事情变得更糟

更新

只需阅读输入的评论,同时键入我的答案。另一个替代消息框的选项是打开文件夹窗口,毕竟文件保存在该窗口中 已创建文件(将Environ$(“APPDATA”)替换为保存位置):

或打开其中一个PDF:

Shell Environ$("COMSPEC") & " /c Start C:\SomeFile.pdf", vbMaximizedFocus
另一个选项

我无法将其放在注释中,因为代码太多了,而是对MessageBox进行API调用,但不要设置MessageBox的所有者(hWnd),将其设置为&H0或&O0。vbSystemModal应使其弹出到顶部。我不知道用户单击“确定”后是否允许您选择excel应用程序窗口:

MessageBox &O0, "My Message", "My Caption", vbOKOnly + vbSystemModal


#If VBA7 And Win64 Then
Public Declare PtrSafe Function MessageBox _
    Lib "User32" Alias "MessageBoxA" _
       (ByVal hWnd As LongLong, _
        ByVal lpText As String, _
        ByVal lpCaption As String, _
        ByVal wType As LongLong) _
    As Long

#Else
Public Declare Function MessageBox _
    Lib "User32" Alias "MessageBoxA" _
       (ByVal hWnd As Long, _
        ByVal lpText As String, _
        ByVal lpCaption As String, _
        ByVal wType As Long) _
    As Long

#End If

我做了一些测试,为你找到了一个潜在的工作

我设置了这个简单的程序来测试您的情况:

Sub test()
    If Application.Wait(Now + TimeValue("0:00:10")) Then
        MsgBox "Time expired"
    End If
End Sub
我运行这个程序,然后最小化所有窗口,当计时器启动时,什么都不会发生。如果我切换到Excel,我可以看到消息框,但没有其他内容

所以我试了一下:

Sub test()
    If Application.Wait(Now + TimeValue("0:00:10")) Then
        ThisWorkbook.Activate
        MsgBox "Time expired"
    End If
End Sub
这一次,当我运行该过程时,最小化所有窗口,而不是什么都看不到,消息框会弹出(但不是Excel窗口)

我认为,通过添加
此工作簿。在
MsgBox
代码之前激活
,您可以在文件中实现同样的效果


这并没有让你完全达到目的,但希望比你现在的状况更好。

*哦,我没有读你的问题的其余部分,我使用了AppActivate并按预期工作,我使用的是MS Office Professional Plus 2010

我无法从GuitarPower获得该方法,但可以将其作为示例使用。不要使用
此工作簿。激活
尝试
AppActivate(“Microsoft excel”)
然后使用
MsgBox

Sub test()
    If Application.Wait(Now + TimeValue("0:00:10")) Then
        AppActivate ("Microsoft excel")
        MsgBox "Time expired"
    End If
End Sub

我尝试了所有其他答案中的大部分:

  • 此工作簿。激活
  • AppActivate()
  • Application.Wait()
  • 睡眠
无论出于何种原因,上述措施都不起作用。我相信,在我们的计算机环境中,有一些真正特定的商业环境可能会造成问题。正如其他人提到的,上述所有解决方案都可能适用于安装了任何版本的Office 2010的全新格式化Windows 7安装,即使是在双监视器设置中。所有这些答案都是+1。此外,我注意到问题只发生在一些特定的工作簿中。非常奇怪的行为,这可能只是一个Office 2010错误,与我在工作簿中所做的事情有关(无论是VBA还是Excel)

话虽如此,但我真正的解决方案(不是最初问题的真正解决方案)不是使用
MsgBox()
。确实存在一些变通方法,我发现表单对我来说是最好的。因此,我没有在这个问题上浪费更多的时间,而是用下面非常简单的代码来替换我原来的
MsgBox()

我可以在
frmMsgBox
中的标签中放入我想要的任何文本,由于这是Excel,我可以通过使用隐藏单元格简单地传递参数


感谢您的帮助。

无论其他应用程序有哪些焦点,这都将在Excel中工作:

在消息框或任何警告之前,输入以下代码:


相信我,这太棒了

并不是说这是一个解决方案,但是Alt-Tab能让你达到目的吗?不,我也试过了。MsgBox不被Windows视为窗口(这里是W7),因此我只能看到Excel2010和FocusExcel2010。但在Excel中,焦点仍然集中在Excel窗口后面的MsgBox上。我可以试着用键盘按“回车”,但这是我唯一没有尝试的。你使用多显示器吗?另外,你能发一些代码吗?我有两个显示器,是的。通常,Excel甚至不会最小化。但是,如果我在另一个屏幕上做一些事情,MsgBox就会放在它下面(当Excel看起来失去焦点时)。另外,是否需要一个消息框?您可以使用其他一些通知方法。用户表单、电子邮件通知、状态栏等。如果没有其他功能,请打开
Sub test()
    If Application.Wait(Now + TimeValue("0:00:10")) Then
        AppActivate ("Microsoft excel")
        MsgBox "Time expired"
    End If
End Sub
Application.ScreenUpdating = False
frmMsgBox.Show
Application.ScreenUpdating = True
AppActivate Application.Caption
DoEvents