Python ExcelVBAマクロファイルを実行する「pywin32(win32com)」

 本記事では、Excelマクロファイル(.xlsm)をPython(.py)で操作する雛形コードを載せました。
まずは、WindowsアプリをPythonで操作するライブラリpywin32(win32com)をpipでインストールします。

pip install pywin32

anaconda環境下では次のようにしてインストールします。

conda install -c anaconda pywin32

 

Excel VBAのサンプルコード

 VBAとはVisual Basic for Applicationsの略でMicrosoft Office製品を動かすプログラミング言語のことです。特にエクセルを動かすVBAExcel VBAと呼びます。
 ここで、本記事で使用するExcel VBAのプログラムを下図に示す。引数valを受け取ってExcelのセルに代入し、セルに数式を代入して掛け算をする仕組みにしています。本雛形コードでは、引数をPythonから与える仕様にしています。

f:id:HK29:20210807134123p:plain

ここで注意です。作成したプロシージャは、引数を設定したプロシージャや、プライベートプロシージャ(Private sub や function)の場合は、下図のようにマクロ名に表示されません。

f:id:HK29:20210807141304p:plain

そのため、そうした場合にプログラムを再編集したい場合は、下図のように「開発」タブのVisual Basicをクリックすることで出来ます。

f:id:HK29:20210807141422p:plain

 

●本プログラム(Pythonスクリプト)について

本プログラム(.py:コードは本記事の文末に記載)は、下図のようにExcel VBAで作成したマクロファイル(.xlsm)と同じフォルダへ置きます。

f:id:HK29:20210807142343p:plain

本コードを実行すると、下図のようにいくつかの.xlsxファイルを生成します。

f:id:HK29:20210807142517p:plain

下図は「3.xlsx」の場合の例です。B列のセルにファイル名と同じ「3」が代入されてるのは、Pythonから代入された値のためです。そして、C列はA列×B列の掛け算の結果です。図中では”C9”を選択していて、図中上側のfxをみると「=A9*B9」と数式になってることがわかります。これは、Excel VBAでセルに数式を代入した結果のためです。

f:id:HK29:20210807143133p:plain

 

■本プログラム
 ファイルの保存書式は、FileFormatで指定します。.xlsxは「51」で.csvは「6」です。

# このPythonスクリプトと実行したいExcelマクロファイルの2つは
# カレントディレクトリへ置いて実行します。
import os
import win32com.client
import time


# Excelのインスタンスを生成する関数
def set_excel_func(select_sheet_name):
    # excelのインスタンスの生成
    xl = win32com.client.Dispatch("Excel.Application")
    
    # 表示設定
    xl.Visible = True
    
    # Excelマクロファイル(.xlsm)を読み取り専用で開く
    # ※絶対パスの必要有り
    wb = xl.Workbooks.Open(Filename = vba_macro_file_path, ReadOnly = 1)
    
    # ワークシートを選択するためのインスタンス生成
    ws = wb.Worksheets(select_sheet_name)
    
    # ワークシートへデータを直入力したい場合
    ws.Range('A1').Value = 'x'
    ws.Range('B1').Value = 'y'
    ws.cells(1, 3).Value = '積'
    
    return xl, wb, ws


def main():
    # マクロを指定するための文字列を作成する
    # 順番に、[Excelマクロファイル名]![モジュール名].[マクロ名]
    excel_macro_name = ''.join([vba_macro_file_name, r'!', 'Module1', r'.', '掛け算'])
    print('excel_macro_name -> ', excel_macro_name)

    # マクロを複数回繰り返し実行する
    for k in range(1, 10, 2):
        print(str(k), '...')
        
        # シートを指定してインスタントの生成
        select_sheet_name = 'Sheet1'
        xl, wb, ws = set_excel_func(select_sheet_name)
        
        # マクロ名を指定して実行。
# 2つ目の引数はVBAのプロシージャへ渡す。最大30
xl.Application.Run(excel_macro_name, k) # 警告を表示しない(ファイル保存の場合の確認を無視するため) xl.DisplayAlerts = False ### ワークブック保存する(※絶対パスの必要有り) # xlsxフォーマットの場合 wb.SaveAs(os.getcwd() + r'/' + str(k) + '.xlsx', FileFormat = 51) # csvフォーマットの場合 #wb.SaveAs(os.getcwd() + r'/' + str(k) + '.csv', FileFormat = 6) # ワークブックを閉じる wb.Close(SaveChanges=True) # アプリケーションを閉じる # この時、処理遅延でエラーになる場合があるため、前後にスリープを入れる time.sleep(1) xl.Application.Quit() time.sleep(1) # 警告を表示を有りに戻す xl.DisplayAlerts = True if __name__ == "__main__": # Excelマクロファイル名 vba_macro_file_name = 'excel_vba_macro.xlsm' # Excelマクロファイルの存在をチェック(※絶対パスの必要有り) vba_macro_file_path = os.getcwd() + r'/' + vba_macro_file_name if os.path.exists(vba_macro_file_path): print(vba_macro_file_path) else: print('vba_file not found') # メイン関数の実行 main() print('finished')

(備考)次のようなエラーが出た場合は、ファイルの指定が絶対パスになっていないためです。ファイルの読み出しだけでなく、保存の場合にも絶対パスの必要があります。

com_error: (-2147352567, '例外が発生しました。', (0, 'Microsoft Excel', '申し訳ございません。excel_vba_macro.xlsmが見つかりません。名前が変更されたか、移動や削除が行われた可能性があります。', 'xlmain11.chm', 0, -2146827284), None)

以上

<広告>