Excel VBAを利用していると、作業内容によってはPythonを利用したい場合があると思います。
そこで、VBAからPythonを呼び出して実行する方法を解説します。
xlwings というライブラリを使用すると、Excel VBAからPythonを実行して、値の読み書きを行う事が可能になります。
これを利用することにより、マクロを実行して一部の処理をした後に、Pythonで機械学習を実行して結果をExcelに書き込み、さらにマクロで処理をさせる と言ったことも出来るようになります。
WshShellオブジェクトを使用してVBAからPythonコマンドを実行させる事もできますが、Excelの値を読み書きするには、xlwings を使用することをオススメします。
使用ライブラリ
インストール:必要
xlwings
を利用することで、Excel VBAからPythonを呼び出せるようになります。
ただし、ライブラリのインストールだけではマクロからPythonを呼び出すことは出来ないため、VBA側で参照設定を行う必要があります。
ライブラリのインストール
コマンドプロンプトを起動してpipで xlwings
ライブラリをインストールします。
pipの使い方はこちらの記事を参照してください。
・関連記事:Pythonライブラリのインストール(pipの使い方)
Successfully installed xlwings-*.*.* と表示されればインストールは成功です。
エクセルの参照設定でxlwingsを追加する
Excel側の参照設定でxlwingsライブラリを追加することで、VBAからRunPython()
という関数でPythonを呼び出せるようになります。
サンプルのExcelファイルは以下のsample.xlsxを使用します。ファイルはpythonスクリプトファイルと同じディレクトリに保存します。
Excelファイルを開き、「開発」メニューからVisual Basicエディタを起動します。
エディタの「ツール」から「参照設定」を開きます。
xlwings にチェックを入れて「OK」をクリックします。
プロジェクト一覧に「参照設定-xlwings.xlam」が追加され、Pythonを呼び出す事が出来るようになります。
設定が完了したら、Excelファイルを sample.xlsm(マクロファイル)として保存します。
VBAからPythonを呼び出すサンプルプログラム
ExcelデータをPyhonで読み込み matplotlib でグラフを作成し、Excelにそのグラフを挿入する例を紹介します。
ディレクトリ構成は以下のようになります。
├── sample.xlsm
└── test.py
test.py のプログラムを以下のように記載します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # ライブラリ設定 import xlwings as xw import pandas as pd import matplotlib.pyplot as plt # マクロから呼び出すプログラム def main(): # シート2020を選択 ws = xw.sheets['2020'] ws.activate() # エクセルの値を読み込む date = xw.Range('A2:A13').value avg = xw.Range('B2:B13').value max = xw.Range('C2:C13').value min = xw.Range('D2:D13').value # matplotlibでグラフ作成 fig = plt.figure() plt.plot(date, avg, label='平均気温') plt.plot(date, max, label='最高気温') plt.plot(date, min, label='最低気温') plt.legend(prop={"family":"MS Gothic"}) # アクティブシートにグラフを挿入(top, leftで貼付け座標を指定) ws.pictures.add(fig, name='MyPlot', update=True, left=sht.range('F1').left, top=sht.range('F1').top) if __name__ == '__main__': main() |
sample.xlsm には、Visual Basicエディタで標準モジュールを追加して、以下のコードを記載します。
1 2 3 | Public Sub Graph() Call RunPython("import test; test.main()") End Sub |
RunPython()
の引数は、 "import pythonファイル名; Pythonファイル名.Pythonプログラム()"
のように呼び出すPythonファイルとプログラムを文字列で指定します。
マクロを実行すると、Excelシートにグラフが追加されます。
デバッグ
xlwingsを実行しているPythonプログラムでエラーが発生すると、以下のようにメッセージが表示されますが、これではデバッグしずらいです。
上記で紹介したサンプルプログラムの場合は、Pythonのデバッグは通常と同じように、開発環境のデバッグを実行できます。
ですが呼び出し元のExcelのBookインスタンスを取得するために xw.Book.caller()
を使用している場合は、Excelとの関連が何もない状態なので、デバッグを実行しても上手く機能しません。
そのため、Pythonプログラムであらかじめmockを設定した後、開発環境のデバッグモードで実行します。
サンプルプログラムです。
1 2 3 4 5 6 7 8 9 10 11 | import xlwings as xw import pandas as pd import matplotlib.pyplot as plt def main(): sht = xw.Book.caller().sheets[0] sht.range('A-1').value = 'Hello xlwings!' if __name__ == '__main__': xw.Book('debug.xlsm').set_mock_caller() main() |
このように、エントリポイントとして実行された時に .set_mock_caller()
で mock を設定することで、開発環境でデバッグを行うことができます。
xlwings操作一覧
xlwingsの使い方として、代表的な関数を紹介します。
ブック操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # 新規ブック作成 wb = xw.Book() # ブックを開く wb = xw.Book(Excelファイルパス) # ブックをアクティブにする wb.activate(steal_focus=False) # 呼び出し元のExcelを取得 xw.Book.caller() # 呼び出し元のExcelとして扱う xw.Book(Excelファイルパス).set_mock_caller() # ブックのフルパスを取得 wb.fullname # ファイル名を取得 wb.name # ブックを閉じる wb.close() # ブックを保存する wb.save(保存先パス) |
シート操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # アクティブブックの全シートを取得 wss = xw.sheets # シート数を取得 wss.count # アクティブなシートを取得 ws = xw.sheets.active # シートを指定して取得(インデックス番号も可) ws = xw.sheets['Sheet1'] ws = xw.sheets[0] # シートをアクティブにする ws.activate() # シートを選択する ws.select() # シート名を取得 ws.name # 画像インスタンスを取得 ws.pictures # グラフインスタンスを取得 ws.charts # シェイプオブジェクトインスタンスを取得 ws.shapes |
セル操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # セル指定 rng = xw.Range('A1') # 列範囲指定 rng = xw.Range('A:D') # 行範囲指定 rng = xw.Range('1:5') # 範囲の指定 rng = xw.Range('A1:D5') rng = xw.Range((1,1), (5,5)) # 範囲の値を取得 rng.value # 範囲に値を書き込む rng.value = 0 # 範囲に日付を書き込む rng.value = datetime(2020, 1, 1) # 範囲に式を書き込む rng.formula = '=A1+A2' |
・関連記事:PythonでExcelファイルを操作する(openpyxl)
・関連記事:pandasでExcelファイルの読み込み(read_excel)
・関連記事:pandasでExcelファイルの書き込み(to_excel)
・関連記事:pandasでCSVファイルを読み込む方法(read_csv)