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

我使用下面的代码从xlwings模块调用VBA中的RunPython:

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

我如何使SolverAdd代码等待,直到RunPython代码完全完成?

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

我会build议以下两个解决scheme之一:

1)用Python scipy.optimize求解器部分,例如使用scipy.optimize

2)把求解器VBA放到它自己的Sub中,并从Python中调用它。 这是目前xlwings下一版本的计划function,请参阅此处 ,但现在可以像现在这样工作(假设wb是您的工作簿):

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

更新 ,自v0.7.1以来,这是现在正确支持:

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

也许有点笨重,但也看看Application.OnTime方法,它可以让你安排代码在设定的时间运行。 所以把你的解算器代码放到另一个proc中,调用RunPython ,然后安排求解器的处理时间为10秒钟。

或者,可能是一个更好的答案,得到的Python代码写入一个Range或文本文件时完成。 具有解算器代码的proc将查看范围或文件,以查看是否完成了python。 如果python没有完成,则安排自己在N秒内重新运行,否则运行求解器。

另一种方法是在Python代码末尾的隐藏工作表中更改一个值,并用一个Worksheet_Change代码片段来启动一些vba代码。 如果隐藏表是“补充”,那么在Python代码的末尾添加这样的内容:

范围('补充','A1')。值=范围('补充','A1'),值+1

而“补充”表中的vba可以是:

私人小组Worksheet_Change(BYVAL目标作为范围)
如果不相交(Target,Me.Range(“A1”))是Nothing
工作表(“Main1”)。范围(“A1”)。WrapText = True
万一
结束小组

请记住, Application.EnableEvents需要= True