如何等待 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
我在 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