如何等待 xlwings 完成 vba 中的 python 代码?

how to wait for xlwings to complete python code in vba?

我在 VBA 中使用以下代码从 xlwings 模块调用 RunPython:

Sub Portfolio_Optimze()
RunPython ("import quotes; quotes.get_quote()")
SolverAdd CellRef:="$H:$H", Relation:=1, FormulaText:="$J:$J"
SolverAdd CellRef:="$B:$G", Relation:=4
SolverOk SetCell:="$H", MaxMinVal:=1, ValueOf:=0, ByChange:="$B:$G", _
    Engine:=1, EngineDesc:=" GRG Nonlinear "
SolverSolve

如何让 SolverAdd 代码等到 RunPython 代码完全完成?

可能有点笨拙,但也可以查看 Application.OnTime 方法,它可以让您在设定的时间将代码安排到 运行。因此,将您的求解器代码放入另一个过程中,调用 RunPython 然后安排求解器过程,比如 10 秒时间。

或者,可能是更好的答案,让 python 代码在完成后写入 Range 或文本文件。带有求解器代码的过程将查看范围或文件以查看 python 是否已完成。如果 python 未完成,则在 N 秒后再次安排自己到 运行,否则 运行 求解器。

开始的一些信息:Excel on Mac 只允许外部进程在 Excel 空闲时写入单元格,即没有 Macros 运行。这就是为什么 Mac 上的 RunPython 调用作为后台进程运行,只有在调用宏完成时才真正启动 运行.

我会建议以下两种解决方案之一:

1) 也在 Python 中对求解器部分进行编程,例如使用 scipy.optimize.

2) 将求解器 VBA 放入其自己的 Sub 中并从 Python 中调用它。这是 xlwings 下一版本的当前计划功能,请参阅 here,但您现在可以像这样解决(假设 wb 是您的工作簿):

app = xlwings.Application(wkb=wb)
app.xl_app.run_VB_macro('SolverMacro')

更新,自 v0.7.1 起,现在已得到正确支持:

>>> solver_macro = wb.macro('SolverMacro')
>>> solver_macro()

另一种方法是更改​​ python 代码末尾的隐藏 sheet 中的值,并使用 Worksheet_Change 代码段来触发一些 vba代码。如果隐藏 sheet 是 "Supplement" 然后在 python 代码的末尾添加这样的东西:

Range('Supplement', 'A1').value = Range('Supplement', 'A1').value +1

"Supplement" sheet 中的 vba 可以是:

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("A1")) Is Nothing Then
        Worksheets("Main1").Range("A1").WrapText = True
    End If
End Sub

记住 Application.EnableEvents 需要 = True