【发布时间】:2017-12-23 05:49:17
【问题描述】:
我一直在使用这个问题的最佳答案中的函数在 VBA(execShell 函数)中运行 shell 脚本,它使用 libc.dylib:
VBA Shell function in Office 2011 for Mac
函数内部有一个while循环,它的运行速度比popen慢得多。我猜这部分是在 shell 中执行的,popen 正在初始化,但我不太明白它在做什么。
Time taken to run popen:
0.01171875 seconds
Time taken to run while loop:
0.8710938 seconds
我想知道如果函数执行需要很长时间,是否可以中止或超时?有没有可以用来处理多个函数调用的方法?我在 shell 脚本中为 curl 命令添加了超时。 "curl --connect-timeout 5 --max-time 10 --retry 2 --retry-delay 0 --retry-max-time 40 ",并且在每次通话前还增加了 0.1 秒的延迟。如果它运行顺利,那将不是问题,但有时它似乎会完全锁定。如果 curl 请求有很长的延迟,我宁愿中止它并继续执行脚本。也许在连续几次失败后完全终止脚本。我认为函数调用将被线性处理,但我认为它可能会同时处理 shell 脚本,这可能会导致问题。理想情况下,我希望获得有关脚本状态的反馈,我尝试使用状态栏来实现该脚本,但是由于 2011 版 Excel 的限制,这不起作用。在运行开始时,我可以看到工作表正在更新并且一切运行顺利,但稍后在脚本中,excel 会冻结,直到它完成。
另一种解决方案是使用 MacScript 命令,但是这个 shell 脚本包含带有“\”和多个引号的正则表达式,并且很难翻译成 applescript,所以我更喜欢使用这种方法,因为它已经工作了。使用 system() 命令不是一个选项,因为 VBA 脚本需要输出。
Private Declare Function popen Lib "libc.dylib" (ByVal command As String, ByVal mode As String) As Long
Private Declare Function pclose Lib "libc.dylib" (ByVal file As Long) As Long
Private Declare Function fread Lib "libc.dylib" (ByVal outStr As String, ByVal size As Long, ByVal items As Long, ByVal stream As Long) As Long
Private Declare Function feof Lib "libc.dylib" (ByVal file As Long) As Long
Function execShell(command As String, Optional ByRef exitCode As Long) As String
Dim file As Long
file = popen(command, "r")
If file = 0 Then
Exit Function
End If
While feof(file) = 0
Dim chunk As String
Dim read As Long
chunk = Space(50)
read = fread(chunk, 1, Len(chunk) - 1, file)
If read > 0 Then
chunk = Left$(chunk, read)
execShell = execShell & chunk
End If
Wend
exitCode = pclose(file)
End Function
【问题讨论】:
标签: excel vba macos shell curl