programing

Excel-VBA에서 파이썬 코드를 호출하는 방법이 있습니까?

jooyons 2023. 6. 24. 09:00
반응형

Excel-VBA에서 파이썬 코드를 호출하는 방법이 있습니까?

매크로가 포함된 Excel 파일(Main.xlsm)을 가지고 있습니다.저는 Main.xlsm-file의 매크로를 추가로 호출할 자회사 Excel 파일(sub.xlsx)을 생성하기 위해 파이썬 파일(python.py )을 가지고 있습니다.python.py 을 실행하여 생성된 이 sub.xlsx 파일은 동일한 작업 디렉토리에 저장됩니다.

이제 Main.xlsm 매크로를 실행하는 동안 이 python.py 을 실행한 다음 이 xlsx 파일을 사용합니다.저는 기본적으로 외부적으로 python.py 을 실행하는 단계를 줄이고 싶습니다.그것에 대한 명령이 있습니까?저는 VBA가 처음입니다.

가장 간단한 방법은 Python 인터프리터를 실행하는 것입니다.Shell지휘권

Shell ("python.exe " & yourScript & " " & arguments)

네, 있습니다.제가 선호하는 방법은 xlwings(https://www.xlwings.org/), )를 사용하는 것이지만 다른 여러 옵션도 있습니다.XlWings는 무료, 오픈 소스이며 사용하기 쉽고 문서도 훌륭합니다.그러나 기능에 제한이 있으므로 필요에 적합한지 확인해야 합니다.

실행이 종료될 때까지 기다려야 하는지, 오류 없이 진행되었는지 여부에 따라 VBA로 파이썬 스크립트를 실행하는 방법은 여러 가지가 있습니다.

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를 사용합니다.콘솔 및 종료 코드 없이 동기화된 셸:

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

저는 바로 여기블로그에서 파이썬달을 보냈습니다.COM 지원 파이썬 클래스인 게이트웨이 클래스라고 하는 패턴을 설정합니다. 명령줄에서 실행되고 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

전체 설명은 여기 원본 블로그 항목에서 확인할 수 있습니다.

이곳의 장점은 포격이 없다는 것입니다.코드가 반환되면 셸링이 완료되었으며 셸링 프로세스가 종료되었는지 등을 한 번 확인해야 합니다.이 게이트웨이 클래스가 훨씬 더 나은 IMHO입니다.

언급URL : https://stackoverflow.com/questions/45410316/is-there-a-way-to-call-a-python-code-in-excel-vba

반응형