マクロを含む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が初めてです。
最も簡単な方法は、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"でインスタンス化されます。 )。
以下は、いくつかの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
完全な解説は、元の ブログエントリにあります
ここでの利点は、砲撃がないことです。コードが返されたら、終了したことがわかります。一度シェル化すると、シェル化されたプロセスが終了したかどうかを確認する必要があります。このゲートウェイクラスは、はるかに優れています。