Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有办法在Excel VBA中调用Python代码?_Python_Vba_Excel - Fatal编程技术网

有没有办法在Excel VBA中调用Python代码?

有没有办法在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(

我有一个包含宏的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(),但也有其他几种选择。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。你能帮帮我吗?