簡體   English   中英

有沒有辦法在Excel-VBA中調用Python代碼?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM