Vba 如何判断是否从即时窗口调用Sub

Vba 如何判断是否从即时窗口调用Sub,vba,excel,immediate-window,Vba,Excel,Immediate Window,有些潜艇我只想从即时窗口运行,比如这个有点危险的潜艇: Public Sub clear() Application.SendKeys "^a", True Application.SendKeys "{delete}", True End Sub 万一你不能解决它;它向应用程序发送ctrl+a和Del,并具有清除光标周围任何内容的效果 我在即时窗口中通过键入clear使用它,即时窗口中的所有内容都将被删除 正如你可能知道的,这艘潜艇非常危险,而且很

有些潜艇我只想从即时窗口运行,比如这个有点危险的潜艇:

Public Sub clear()

Application.SendKeys "^a", True
Application.SendKeys "{delete}", True

End Sub
万一你不能解决它;它向应用程序发送ctrl+a和Del,并具有清除光标周围任何内容的效果

我在即时窗口中通过键入
clear
使用它,即时窗口中的所有内容都将被删除

正如你可能知道的,这艘潜艇非常危险,而且很容易意外呼叫。因此,我只希望在从即时窗口调用时运行它

  • 不是从另一艘潜艇来的
  • 不是来自表单控件
  • 不是来自ActiveX(虽然这实际上只是一个子控件)
  • 不是来自用户调用(通过“开发人员/宏”选项卡)
而且也不是来自任何其他来源(我列出了所有这些,因为我认为即使你不能直接判断它是由即时窗口调用的,你也可以通过排除其他选项来间接判断)

这可以通过编程实现吗?理想情况下,我只想在
clear()
sub的开头进行一个简单的布尔检查,告诉它除非立即窗口调用,否则不要执行任何操作


请注意
一种方法可能是通过使用调用堆栈(ctrl+L打开对话框),因为我注意到即时调用在堆栈中没有留下任何痕迹,而调用
clear()
的sub被列出,因此可以排除。但我不确定如何通过VBA访问此窗口,我知道这不是您问题的答案,但如果您想“清除”即时窗口,我使用以下方法:

Sub clear()
For i = 0 To 100
    Debug.Print ""
Next i
End Sub

一个简单的解决方案是添加一个参数

Public Sub clear(sCaller As String)

If sCaller = "Immediate" Then
    Application.SendKeys "^a", True
    Application.SendKeys "{delete}", True
End If

End Sub

这也可能不是您想要的,但显然会将风险降至最低

我发现了一种结合了一些想法的方法:

Public Sub clear(Optional s As Variant)

If TypeName(Application.Caller) = "Error" And IsMissing(s) = False Then
'Do code
End If

End Sub
发生的情况是,如果从范围(仅功能)或按钮调用sub,则
TypeName
测试会捕捉到这一点,因为它们将分别返回
range
String
。错误选项包括即时窗口、子窗口或用户调用。额外的参数不能由用户给出,所以这是不可能的。最后,我们希望子调用不会包含该参数

s
变体
,因此您可以在即时窗口中键入
清除任何内容
,而无需将
waterver
放入
(表示文本)


显然,通过适当的论证可以使其更加安全。显然,它并不像“希望”这个词所要表达的那样理想!当然,它也不能真正回答问题。

你说“这艘潜艇非常危险,而且很容易意外呼叫。”。“因此,我将该函数重命名为例如
cleardebug
,这样它就不同于任何类似
listbox.clear()
的函数,并且不再意外调用它。有人不应该意外调用名为
cleardebug
的函数,也不能想象这种情况会意外发生。@Peh我同意这可能有助于vba调用,但我不完全相信有两个原因;首先,我能想到的意外调用的主要形式是在“运行宏”窗口中单击错误的宏-更改名称并不能解决这个问题。其次,键入
cleardebug
感觉比手动执行ctrl+a+del更费力(显然,您可以选择一个不同的名称,但是找到一些明显到足以让人难忘但又模糊到在VBA中没有其他意义的内容,并且足够简洁到可以键入很难)!好的,让我说,在网上有大约1000个关于如何清除即时窗口的讨论、how-tos和教程,以及大约10种不同的解决方案。如果有一种解决方案,比如将即时窗口检测为函数调用方(或者像您建议的那样),我想有人已经找到了。我认为除了这些讨论已经指出的问题之外,没有更好的解决办法了。@Peh这是正确的观点,但是一个新的问题措辞可能会吸引一些不同的想法,我在我做的研究中没有提到这种方法(几乎可以肯定的是,这是一种徒劳无益的做法,但可能是因为没有考虑这一做法)我一直使用MZ工具上提供的按钮来清除即时窗口-不幸的是,不再是免费的。我在其他地方看到过这种情况,在大辩论中,我不喜欢它将光标留在窗口底部的方式。而且,正如你所说,它回答了我的具体情况,但不是实际问题(尽管解决方法的精神是如此!)事实上,它甚至可以是一个可选参数,因为用户/按钮单击无法传递字符串,而且很难意外地键入子项。因此,使用它
可选
只会避免错误消息,但不会降低安全性,或者将原始代码更改为Application.SendKeys“^g^a{DEL}”小点:您的参数是可选的,因此在调用例程时根本不需要提供参数,无论是由用户(可能但不太可能)还是由另一个子系统提供。@Rory,但是我检查它是否
正在减少
,使得子系统中的代码必须运行,而不是整个子系统运行(为了避免意外调用时出错)抱歉-我忽略了这一部分。从技术上讲,额外的参数可以由用户给出,只是不会意外发生!;)