有没有办法在Excel VBA中调用Python代码?
我有一个包含宏的Excel文件(Main.xlsm)。我有一个Python文件(Python.py)来生成一个辅助Excel文件(sub.xlsx),我将在Main.xlsm-file的宏中进一步调用它。运行python.py生成的这个sub.xlsx文件保存在同一个工作目录中有没有办法在Excel VBA中调用Python代码?,python,vba,excel,Python,Vba,Excel,我有一个包含宏的Excel文件(Main.xlsm)。我有一个Python文件(Python.py)来生成一个辅助Excel文件(sub.xlsx),我将在Main.xlsm-file的宏中进一步调用它。运行python.py生成的这个sub.xlsx文件保存在同一个工作目录中 现在我想让这个python.py在Main.xlsm宏运行期间执行,然后使用这个xlsx文件。我基本上希望减少在外部执行python.py的步骤。有命令吗?我是VBA新手。是的,有。我比较喜欢的方法是通过xlwings(
现在我想让这个python.py在Main.xlsm宏运行期间执行,然后使用这个xlsx文件。我基本上希望减少在外部执行python.py的步骤。有命令吗?我是VBA新手。是的,有。我比较喜欢的方法是通过xlwings(),但也有其他几种选择。XlWings之所以伟大,是因为它是免费的、开源的、易于使用的,并且有大量的文档。不过,还有一些功能限制,因此您必须检查它是否符合您的需要。最简单的方法是使用
Shell
命令运行python解释器
Shell ("python.exe " & yourScript & " " & arguments)
使用VBA运行python脚本有多种方法,这取决于您是否需要等待执行结束并知道它是否正常运行 使用,异步使用控制台:
Public Sub RunPython(file As String, ParamArray args())
Shell "python.exe """ & file & """ " & Join(args, " ")
End Sub
有,同步,无控制台:
Public Function RunPython(file As String, ParamArray args())
Shell "pythonw.exe """ & file & """ " & Join(args, " ")
End Function
有,同步,无控制台,带退出代码:
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
我有一个完整的计划。我建立了一个模式,我称之为gateway类,它是一个启用COM的Python类,如果从命令行运行,它将注册自己,一旦注册,它将用CreateObject(“foo.bar”)实例化
下面是一个VBA调用使用一些scipy函数的Python类的好例子
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
选项显式
子测试PythonskewedNormal()
作为对象的Dim skewedNormal
设置skewedNormal=CreateObject(“SciPyInVBA.PythonSkewedNormal”)
模糊和长
lSize=100
将shtData设置为Excel.工作表
Set shtData=thishworkbook.Worksheets.Item(“Sheet3”)好主意,请投票表决。XlWings不是在一个线程中工作吗?很棒的插件!我不知道这个,谢谢!进行(其他)投票。当然我会检查@Gabor。谢谢您的回复。@Bathsheba最近已添加到xlwings。那么请保持对VBA的了解(远离VBA:),我希望您能找到您需要的。有趣的问题。@Jean-Françoisfar感谢您在问题中表现出的兴趣:p从我的角度来看(也适用于其他专有和繁琐的系统),有时最好1)将数据导出为CSV 2)运行python脚本以轻松处理数据,3)重新导入excel/无论什么,因此我们也使用此技巧,而不是尝试用子语言编写代码:)我使用“网关类”。之所以称为网关,是因为它为Excel VBA开发人员打开了Python生态系统的丰富世界。我添加了一个完整的答案(使用不同的示例)。感谢您的回复@Uri。但一个小问题是,它是python的命令还是VBA的命令?我需要在VBA中执行它。@UriGoren您的脚本根据此上下文是Main.xlsm?不,这是您的python脚本文件名您可能还需要使用python
解释器的完整路径,以防您没有它您的路径
非常好-如果可以的话,我会投更多的票。有趣的建议!但是,如果我错了,请纠正我,但是现在您有两个进程要启动(python脚本,然后是Excel),对吗?@Joel:如果是两个进程,那么这与Shell相同。但是,如果比特数相同,则python运行时dll将加载到Excel.exe中。如果bitness不同,则有两个进程,以下是我对该主题ModuleNotFoundError的调查:没有名为“win32com”的模块@drgs没有名为“xyz”的模块意味着您需要安装“xyz”。@SMeaden在运行代码后,我收到以下错误:TypeError:找不到承载COM对象的脚本-请在对象中设置_reg\u class\u spec。我还尝试使用test1.py--register
在cmd中注册相同的代码。然后我得到一个NumPy的modulenotfound错误。虽然我已经安装了NumPy。你能帮帮我吗?