web-dev-qa-db-ja.com

Python Excel-VBAのコードを呼び出す方法はありますか?

マクロを含むExcelファイル(Main.xlsm)があります。 Main.xlsm-fileのマクロでさらに呼び出す副Excelファイル(sub.xlsx)を生成するためのPythonファイル(python.py))があります。このsub.xlsx- python.pyの実行によって生成されるファイルは、同じ作業ディレクトリに保存されます。

ここで、このpython.pyをMain.xlsmマクロの実行中に実行し、このxlsx-fileを使用したいと思います。基本的に、python.pyを外部で実行するステップを減らしたいと思います。そのためのコマンドはありますか?私はVBAが初めてです。

18

最も簡単な方法は、Shellコマンドを使用してpythonインタープリターを実行することです。

Shell ("python.exe " & yourScript & " " & arguments)
26
Uri Goren

はいあります。これを行うための好ましい方法は、xlwings( https://www.xlwings.org/ )を使用することですが、他にもいくつかのオプションがあります。 XlWingsは、無料のオープンソースで使いやすいだけでなく、優れたドキュメントを備えているため、すばらしいです。ただし、機能にはいくつかの制限があるため、ニーズに合っているかどうかを確認する必要があります。

19
Gabor

実行の終了を待ってエラーなしで実行されたかどうかを知る必要があるかどうかに応じて、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
15
Florent B.

私はブログでPython月を丸ごと 持っていました 。 COMが有効なゲートウェイクラスを呼び出すパターンを確立しますPythonクラス、コマンドラインから実行し、登録されたらCreateObject( "foo.bar"でインスタンス化されます。 )。

以下は、いくつかのscipy関数を使用するPythonクラスを呼び出すVBAの良い例です

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

完全な解説は、元の ブログエントリにあります

ここでの利点は、砲撃がないことです。コードが返されたら、終了したことがわかります。一度シェル化すると、シェル化されたプロセスが終了したかどうかを確認する必要があります。このゲートウェイクラスは、はるかに優れています。

0
S Meaden