【问题标题】:How to call another module without returning to the first one after completion?完成后如何调用另一个模块而不返回第一个模块?
【发布时间】:2013-06-10 16:03:20
【问题描述】:

这可能是我在这里问过的最愚蠢的问题,但很难找到此类问题的答案。

我有一个带有一堆模块/子程序的程序,每个模块/子程序计算一个不同的变量。它们非常复杂,所以我喜欢将它们分开。现在我想要一个较早的模块根据用户输入跳到另一个模块。我以为我可以为此使用call (sub name) 方法,但随后程序返回到调用行所在的位置,并从中断处继续执行该模块。

例子:

模块 1:

Sub NewPracticeSub()

    Call otherpracticesub

    MsgBox ("We've gone back to this sub... :(")

End Sub

模块 2:

Sub otherpracticesub()

    MsgBox ("We're in the other practice sub!")

End Sub

我不希望它返回到模块 1。如果没有它在模块 2 完成后返回完整的模块 1,我该怎么做才能让它将控制权切换到模块 2?

我觉得我只是使用了最令人困惑的语言来解释所有这些,但无论如何感谢您的帮助!

编辑:我知道我可以互换使用模块和子这两个词,而且我知道它们是不同的。我喜欢将每个子程序(在我的程序中每个子程序都非常大)保存在它们自己的模块中,因为这样更容易跟踪它们,并且更容易向其他人解释/演示应用程序流程。

【问题讨论】:

  • 我不希望它返回到模块 1。 为什么不呢? 这就是调用堆栈的工作原理。下面约翰的回答是一个很好的解决方法,但可能您需要更好地组织您的子例程和调用。
  • 您可以在您的子程序中使用End,但这会中止所有运行时过程,杀死所有变量等,应该避免使用。

标签: vba excel excel-2010 excel-2013


【解决方案1】:

我认为您正在寻找的只是命令Exit Sub,它将使程序离开子程序而不再继续,但是您通常想要这样做的方式是,而不是调用Sub,而是调用返回布尔值的Function

所以,例如:

Public Function MyFunc() as Boolean
   ....
   If [good] MyFunc = True
   Else MyFunc = False
End Function

然后你可以按照以下方式做一些事情:

Sub MyCallingSub()
   ...
   If MyFunc = True then Exit Sub
   Else ...
End Sub

它只是增加了更多的灵活性和能力,让您可以选择是否要在您的潜艇中继续前进。

希望这是有道理的。

【讨论】:

  • 同意。把你的电话放在一个 If/Then 循环中。 VBA 总是会返回到您开始的任何子/模块,结束它的唯一方法是返回到该子/模块并退出子。
【解决方案2】:

除了使用我将在下面描述的丑陋的End 语句(强烈建议您避免)之外,我不知道有任何方法可以绕过调用堆栈。甚至 John 的响应也必然返回到调用过程,并评估另一个语句以确定是继续还是结束。

这可能会产生不良结果,这就是为什么我不愿推荐它的原因,以支持相对于调用堆栈正确构建代码、循环等。

在任何情况下,您都可以在您的子子例程中使用End 语句,而无需任何类型的公共/全局变量。这仍然允许您灵活地决定何时何地调用 End 语句,因此不必总是调用它。

Sub NewPracticeSub()

    Call otherpracticesub, True

    MsgBox ("We've gone back to this sub... :(")

End Sub

Sub otherpracticesub(Optional endAll as Boolean=False)

    MsgBox ("We're in the other practice sub!")

    If endAll then End '## Only invoke End when True is passed to this subroutine
End Sub

为什么我说this method should be avoided,来自 MSDN:

"注意 End 语句突然停止代码执行,没有 调用 Unload、QueryUnload 或 Terminate 事件或任何其他事件 Visual Basic 代码。您已放置在 Unload、QueryUnload、 并且不执行窗体和类模块的终止事件。 从类模块创建的对象被销毁,文件使用打开 Open 语句已关闭,程序使用的内存为 释放。其他程序持有的对象引用无效。

End 语句提供了一种强制程序停止的方法。为了 正常终止 Visual Basic 程序,您应该卸载所有 形式。一旦没有其他程序,您的程序就会关闭 持有对从公共类模块创建的对象的引用 并且没有代码执行。”

【讨论】:

  • 我决定硬着头皮花几个小时以更好的方式重新安排我的子例程,这样我就完全不用处理 End 方法了。谢谢你的建议!付出努力是值得的,现在我不必担心会出现更多问题。
  • @TheTreeMan 这很糟糕,但你是对的,从长远来看,你将拥有一个更稳定的程序/应用程序。干杯!
  • 您唯一需要使用 END 的时候是您想重置全局变量。但这通常意味着您在这种情况下犯了一些严重的编码错误。
【解决方案3】:

它总是会返回,但这并不意味着它是一个问题。我建议你使用 Exit Sub 如下:

Sub NewPracticeSub()

Call otherpracticesub

**Exit Sub**
'Nothing more can execute here so its no longer a worry

结束子

模块 2:

sub otherpracticesub()

MsgBox ("We're in the other practice sub!")

结束子

【讨论】:

    猜你喜欢
    • 2019-09-04
    • 1970-01-01
    • 2021-06-08
    • 1970-01-01
    • 1970-01-01
    • 2015-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多