I have an Excel file (Main.xlsm) containing macros. I have a Python file (python.py) to generate a subsidiary Excel file (sub.xlsx) which I would further call in the macros of Main.xlsm-file. This sub.xlsx-file which is generated by the run of python.py is saved in the same working directory.
Now I want to make this python.py to be executed during the run of the Main.xlsm macros and then use this xlsx-file. I basically want to reduce the step of executing python.py externally. Is there a command for that? I am new to VBA.
最简单的方法是使用Shell
命令运行python解释器
Shell ("python.exe " & yourScript & " " & arguments)
Yes, there is. My preferred way of doing this is through xlwings ( https://www.xlwings.org/ ), but there are several other options as well. XlWings is great because it's free, open source and easy to use, with great documentation. There are some feature limitations though, so you'd have to check if it fits your needs.
There are multiple ways tu run a python script with VBA depending on whether you need to wait for the end of the execution and know if it went without error.
With Shell , asynchronous with console:
Public Sub RunPython(file As String, ParamArray args())
Shell "python.exe """ & file & """ " & Join(args, " ")
End Sub
With Shell , synchronous without console:
Public Function RunPython(file As String, ParamArray args())
Shell "pythonw.exe """ & file & """ " & Join(args, " ")
End Function
With WScript.Shell , synchronous without console and with exit code:
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
I had a whole Python month on my blog right here . I establish a pattern which I call the gateway class which is a COM enabled Python class, it will register itself if run from the command line and once registered is instantiated with CreateObject("foo.bar").
Here is a good example of VBA calling a Python class that uses some scipy functions
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)
and the calling VBA code
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
Full commentary can be found at the original blog entry here
The advantage here is that there is no shelling. When the code it returns, you know it has finished, with shelling once has to check if the shelled process has ended etc. This gateway class is much better IMHO.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.