我的简单MsgBox VBA会在我点击“确定”之前暂停整个电子表格,怎么办?

5
请您耐心听我简单阐述一下:我有一个基本的交易电子表格,它会输入实时价格,并在价格超过我的目标入场价时,在单元格AB4中显示文本“买入”。如果我持有该股票且价格低于我的目标,则同一单元格将显示“卖出”。无论如何,电子表格还会自动发送订单来执行交易。
我只是想要一个消息框,在出现信号时提醒我记笔记。我只需要一个提醒,但我确实需要它,因为我总是会忘记。
在阅读了这里的许多帖子之后,这是我的第一次尝试:
Private Sub worksheet_calculate()
 If Range("AB4").value = "BUY" Or Range("AB4").value = "SELL" Then
  MsgBox ("Record Catalyst")
 End If
End Sub

似乎可以工作,但是一旦我点击“确定”,消息框就会立即重新出现。 只要“买”或“卖”的文本显示,无论我点击多少次,消息框都不会消失。
所以我再次搜索,找到了一种让消息框只出现一次的方法:
Private Sub worksheet_calculate()
If ActiveSheet.Range("BV4").Text = "Triggered" Then Exit Sub
  If Range("AB4").value = "BUY" Or Range("AB4").value = "SELL" Then
   MsgBox ("Record Catalyst")
ActiveSheet.Range("BV4") = "Triggered"
End If
End Sub

似乎很有效,但是如果我不点击“确定”让消息框消失,整个电子表格就不再工作了(即价格不再更新,计算也不再执行等)!它似乎只是在等待我先点击该可恶的“确定”。这是一个重大问题,因为如果当消息框出现并且电子表格被停止时,我不在场,那么我的投资组合中另一只股票的价格达到目标,电子表格甚至都不会知道,更不用说自动下单了。
为什么这个简单的程序会使电子表格停止运行,如何解决我最初的“简单”消息框问题?我不想在电子表格上使用条件格式,因为它已经有太多有条件格式的单元格了。
谢谢各位专家!

8
消息框是模态窗口,需要用户在继续前执行一个动作。你可以创建一个简单的用户窗体,并将其作为非模态显示(不会打断你的电子表格)。或者使用状态栏,而不是使用消息框。 - brettdj
你为什么需要首先使用MsgBox?你为什么不直接将其删除,然后添加一个代码运行次数的跟踪器(如果你需要追踪它或其他什么)? - L42
哦,我明白了......我不知道它是“模态”的。好的,让我研究一下用户窗体,看看它们如何帮助。谢谢你的指引! - Untitled
2个回答

5

看起来主要的问题是MsgBox不会超时并消失,因为消息只是提供信息。

使用下面的代码,提示消息将在2秒钟内超时并允许子程序结束。

Private Sub worksheet_calculate()
    If ActiveSheet.Range("BV4").Text = "Triggered" Then Exit Sub
        If Range("AB4").Value = "BUY" Or Range("AB4").Value = "SELL" Then

            Set objShell = CreateObject("Wscript.Shell")

            intReturn = objShell.Popup("Record Catalyst", _
                2, , wshOk)

            If intReturn = 1 Then
                'do something if you click ok
            ElseIf intReturn = -1 Then
                'do something if times out alone, like record in a diff sheet
            End If

            ActiveSheet.Range("BV4") = "Triggered"

            Set objShell = Nothing

    End If
End Sub

希望这能解决你的问题。

哇,那很棒。只有两个问题。在这两秒钟内,电子表格是否仍会停止工作?如果我离开电脑超过两秒钟,那么是否意味着我可能会错过任何消息? - Untitled
@Untitled 是的,如果您想在代码中缩短计时器,只需更改intReturn变量中的“2”。对于未接收到的消息,我建议创建一个名为recorded_logs的新工作表,并记录代码所做的每个“触发”更改和时间。如果您需要有关记录代码的帮助,我可以提供一些帮助。 - Miguel_Ryu

1
如果Windows信使服务正在运行(默认情况下,我曾在每台计算机上都尝试过此操作),则您可以使用Shell函数向自己发送消息。这类似于@Miguel_Ryu的方法,但有一个例外,即Shell将异步运行 - 它完全不会阻塞。以下示例演示了如何操作(显然,您需要将“Comintern”替换为您的Windows用户名):
Sub NonBlockingMessage()

    Dim i As Integer

    Shell "msg Comintern Look at me, I'm non-blocking!", vbHide

    For i = 1 To 10000
        Debug.Print i
    Next i

End Sub

你会看到弹出消息,然后在循环执行时看到数字滚动。这也有一个优点,即消息不仅限于代码运行时。除非您使用/time:参数设置超时,否则它将一直保留在那里,直到被解除,无论您的代码是否在此期间完成。
更好的是,消息将堆叠。如果您在不解除第一条消息的情况下两次运行上面的测试代码,则仍将获得两者的消息。

不可能!那将是一个非常聪明的解决方案。太棒了,Comintern,谢谢你的好主意! - Untitled

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接