[英]Is there a way to call a Python code in Excel-VBA?
我有一個包含宏的Excel文件(Main.xlsm)。 我有一個Python文件(python.py)來生成一個輔助Excel文件(sub.xlsx),我將在Main.xlsm文件的宏中進一步調用它。 這個由python.py運行生成的sub.xlsx文件保存在同一個工作目錄中。
現在我想讓這個python.py在Main.xlsm宏運行期間執行,然后使用這個xlsx文件。 我基本上想要減少外部執行python.py的步驟。 那是否有命令? 我是VBA的新手。
最簡單的方法是使用Shell
命令運行python解釋器
Shell ("python.exe " & yourScript & " " & arguments)
就在這里。 我首選的方法是通過xlwings( https://www.xlwings.org/ ),但也有其他幾個選項。 XlWings很棒,因為它是免費的,開源的,易於使用的,具有出色的文檔。 但是有一些功能限制,因此您必須檢查它是否符合您的需求。
使用VBA運行python腳本有多種方法,具體取決於您是否需要等待執行結束並知道它是否沒有錯誤。
使用Shell ,與控制台異步:
Public Sub RunPython(file As String, ParamArray args())
Shell "python.exe """ & file & """ " & Join(args, " ")
End Sub
使用Shell ,無需控制台同步:
Public Function RunPython(file As String, ParamArray args())
Shell "pythonw.exe """ & file & """ " & Join(args, " ")
End Function
使用WScript.Shell ,無需控制台同步和退出代碼:
Public Function RunPython(file As String, ParamArray args()) As Long
Dim obj As Object
Set obj = CreateObject("WScript.Shell")
RunPython = obj.Run("pythonw.exe """ & file & """ " & Join(args, " "), 0, True)
End Function
我的博客上有一整個Python月份 。 我建立了一個模式,我稱之為網關類,它是一個支持COM的Python類,如果從命令行運行,它將注冊自己,並且一旦使用CreateObject(“foo.bar”)實例化注冊。
這是VBA調用Python類的一個很好的例子,它使用了一些scipy函數
import numpy as np
import pandas as pd
from scipy.stats import skewnorm
class PythonSkewedNormal(object):
_reg_clsid_ = "{1583241D-27EA-4A01-ACFB-4905810F6B98}"
_reg_progid_ = 'SciPyInVBA.PythonSkewedNormal'
_public_methods_ = ['GeneratePopulation', 'BinnedSkewedNormal']
def GeneratePopulation(self, a, sz):
# https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.seed.html
np.random.seed(10)
# https://docs.scipy.org/doc/scipy-0.19.1/reference/generated/scipy.stats.skewnorm.html
return skewnorm.rvs(a, size=sz).tolist()
def BinnedSkewedNormal(self, a, sz, bins):
# https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.seed.html
np.random.seed(10)
# https://docs.scipy.org/doc/scipy-0.19.1/reference/generated/scipy.stats.skewnorm.html
pop = skewnorm.rvs(a, size=sz)
bins2 = np.array(bins)
bins3 = pd.cut(pop, bins2)
table = pd.value_counts(bins3, sort=False)
table.index = table.index.astype(str)
return table.reset_index().values.tolist()
if __name__ == '__main__':
print("Registering COM server...")
import win32com.server.register
win32com.server.register.UseCommandLine(PythonSkewedNormal)
和調用VBA代碼
Option Explicit
Sub TestPythonSkewedNormal()
Dim skewedNormal As Object
Set skewedNormal = CreateObject("SciPyInVBA.PythonSkewedNormal")
Dim lSize As Long
lSize = 100
Dim shtData As Excel.Worksheet
Set shtData = ThisWorkbook.Worksheets.Item("Sheet3") '<--- change sheet to your circumstances
shtData.Cells.Clear
Dim vBins
vBins = Array(-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5)
'Stop
Dim vBinnedData
vBinnedData = skewedNormal.BinnedSkewedNormal(-5, lSize, vBins)
Dim rngData As Excel.Range
Set rngData = shtData.Cells(2, 1).Resize(UBound(vBins) - LBound(vBins), 2)
rngData.Value2 = vBinnedData
'Stop
End Sub
這里的優點是沒有炮擊。 當它返回的代碼時,你知道它已經完成了,炮擊一旦檢查炮轟進程是否已經結束等等。這個網關類是更好的恕我直言。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.