【问题标题】:Running a bat file from Excel VBA macro and then executing additional code only after the bat file has executed从 Excel VBA 宏运行 bat 文件,然后仅在 bat 文件执行后才执行附加代码
【发布时间】:2017-10-23 18:32:32
【问题描述】:

我通常不在 VBA 中编写代码,但需要创建一个 VBA 宏,我可以从中运行一个执行 python 脚本的 .bat 文件。我已经能够做到这一点,但是由于程序在 excel 环境之外运行,我需要确定 .bat 文件何时完成,并向 excel 环境返回一条消息。 这是我目前所拥有的:

Shell ("CMD.EXE /c c:\IndexTrader\run_file\index_trader.bat")

一旦上述 .bat 文件运行,我如何才能在 excel 环境中打印一条消息,表明 .bat 文件已执行。 如果我在 .bat 文件命令之后运行顺序代码(参见上面的代码),由于 .bat 文件是在 excel 环境之外执行的,因此即使 .bat 文件尚未完成,在此命令之后运行的任何顺序代码也会运行。 有没有办法输出一条消息或参数表明.bat文件已执行,然后只执行VBA中的任何顺序代码。

【问题讨论】:

  • 1) 让bat 文件在执行后创建一个文件(即-.txt)。然后您可以使用filesystemobject 在继续代码之前检查该文件是否存在。 Bat 文件也可以在代码开头销毁该文件 2) 如果您知道 python 脚本最多只需要 10 秒左右,您可以使用 VBA Application.Wait 来保持执行,或 Sleep API。
  • @ScottHoltzman 方法确实有效(之前尝试过),但只是另一个想法,让 bat 程序设置系统环境变量怎么样,然后让 vba 等到 environ 变量设置为具体值。没试过,不过我觉得和创建文件是一样的。
  • @Rosetta - 值得尝试一下 :)
  • @ScottHoltzman 在我看来我的想法只是一个死胡同...stackoverflow.com/questions/171588/…

标签: python excel batch-file vba


【解决方案1】:

完全披露:改编自Return result from Python to Vba 它本身受到Capture output value from a shell command in VBA?的影响

顺便说一句,如果您只想从 VBA 执行 python 脚本,那么请转到here。

基本上你需要创建一个WshShell 对象并调用它的WshShell.Exec。这将为您提供运行批处理文件的进程的句柄,甚至可以用于从 stdOut、stdErr 等中提取数据。

您需要的 VBA 代码是:

Public Function runProcess(cmd As String) As String

    Dim oShell As Object
    Dim oExec As Object, oOutput As Object
    Dim s As String, sLine As String

    Set oShell = VBA.CreateObject("Wscript.Shell")    

    Set oExec = oShell.Exec(cmd)
    Set oOutput = oExec.StdOut

    While Not oOutput.AtEndOfStream
        sLine = oOutput.ReadLine
        If sLine <> "" Then s = s & sLine & vbNewLine
    Wend

    Set oOutput = Nothing: Set oExec = Nothing
    Set oShell = Nothing

    runProcess = s

End Function

您可以像在您的示例中那样调用它,方法是:

Dim out_str As String
out_str = runProcess("c:\IndexTrader\run_file\index_trader.bat")
MsgBox "Script complete!"

您使用此方法获得的额外好处是您可以捕获该进程输出,从而将消息从您的 python 脚本传递回 VBA/Excel。

即使忽略返回值,在时间控制返回调用函数时也可以保证过程完成。

如果你是.bat 文件,你可以使用命令行参数:

Dim out_str As String
Dim arg1 As String
arg1 = "6"
out_str = runProcess("c:\IndexTrader\run_file\index_trader.bat " & arg1)
MsgBox "Script complete!"

【讨论】:

  • 您好 Linford,非常感谢您,这非常有效。 :-)
  • 嗨 Linford,我在 python 中创建了一个输入函数,需要用户输入一个值。我尝试再次运行脚本(从 VBA),但它只会导致 excel 挂起和关闭。我相信这是因为程序无法在没有输入的情况下运行(它正在等待)。如果我从 .cmd/python 运行 python 脚本,系统会提示我输入,一旦输入,代码将继续运行。如何从您在上面提供的 VBA 脚本中执行此操作?
  • 嗨@user8689353 - 您所描述的是一个“交互式”python 脚本。如果你想保留这个方法,你应该问一个关于从 VBA 创建交互式 shell 会话的问题。但是,我建议您更改您的 python 脚本,以便它从命令行参数获取所需的参数,而不是从手动交互。你可以看到如何做到这一点here
  • 您好 Linford,谢谢您,您是一位真正的专家,感谢您的帮助。 :-) 我所做的唯一更改是在 bat 文件中传递参数,而不是在 runProcess 函数中,然后在 python 脚本中使用 import sys 来获取传递的参数值(arg1)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-13
  • 2015-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多