~VBAマクロ、もう全部Pythonに任せてみませんか UiPath×Pythonでやってみた~

はじめに

初めまして。皆様、Excelのデータを自動で加工するとき何を使いますか? 

やはりVBAマクロという方が多いのではないでしょうか。 

ただVBAは20年以上も開発されていなく、他の言語なら簡単に出来るのにVBAでは、、、 

なんて経験一度や二度ではないと思います。 

そんな中RPAツールである「UiPath」でPythonが実行出来るアクティビティがあることを知ったので、VBAと親和性の高いUiPathを絡めて、

今回はPythonVBAマクロの比較、Pythonの利点、Pythonアクティビティの使い方についてご紹介したいと思います。 

UiPathとPythonの紹介 

まず初めに、UiPath、Pythonについてご紹介していきます。 

UiPath

UiPath社が開発をしているRPAツールで世界シェア約45%を占めており、最も有名なRPAツールと言っても過言ではありません。アクティビティと呼ばれる部品を組み合わせて定期処理を構築し、人間の定期作業を自動化します。 
またRPAとは、ロボティックプロセスオートメーション」の頭文字を取ったものであり、人間がPCを使って定期的に行っている作業を、ロボットと呼ばれるシステムに自動で遂行させる仕組みのことを言います。

Python

1991年から開発され、今なお活発に開発がされている人気の言語です。特に機械学習の分野で重宝され、また直感的で書きやすく非プログラマにも業務改善ツールとして愛用されています 

PythonとVBAの比較 

PythonとVBAを表で比較してみました。 

◎:優れている評価

△:制限等あり減点がある評価

✕:通常よりも大きく減点がある評価

評価観点 Python VBA コメント
言語としての開発

Pythonは現在も開発中。最新バージョンは3.12

VBAは2008年から開発されていない

実行環境

PythonはWindows、MacOS、Linuxで利用可能
VBAはExcelのみ

ライブラリ数

Pythonは管理されている外部ライブラリの数が約17.5万
機械学習に使用されるものもあれば、最近ではスマホアプリを作成するものもある

VBAは管理された外部ライブラリはない

環境構築

PythonはPCごとにインストールが必要。

また、違うバージョンを利用したい場合はその都度インストールが必要。

VBAはExcelさえあれば実行可能 

コードの書きやすさ

Pythonは直感的な書き方が可能

VBAは他のプログラミング言語には無い少し癖のある書き方がある 

エディタ

Pythonは好きなエディタで開発可能。

VBAは基本的にはExcel内のエディタのみ

外部データ連携

VBAはExcelシートのデータのみ利用可能

PythonはDB連携が可能

 

サンプルプログラムでの比較

次にExcelに記載された下記のような表から、25歳以下、名前に「test 」が含まれているデータ行を別シートに転記するという簡単なプログラムで比較してみます。 

まずはPythonです。

### 処理部分を抜き出しています。全コードは最後に記載いたします。 ###
    # Excelファイルを読み込み、シートに存在する表を変数dfに設定
    ### dfとは、pandasで作成される変数の型がDataFlame型と呼ばれるためその略称
    df = pd.read_excel(excel_file_name, sheet_name=data_sheet_name, header=0)

    # 年齢が25歳以下かつ、名前に「test」が含まれている行をフィルタリング
    filter_df = df[(df['年齢'] <= age) & (df['名前'].str.contains("test"))]

    # 既に存在するExcel内で、指定したシートに今回フィルタリングしたデータを転記
    with pd.ExcelWriter(excel_file_name, engine="openpyxl", mode="a", if_sheet_exists="overlay") as writer:
        filter_df.to_excel(writer, sheet_name=result_sheet_name, startrow=0, startcol=0, header=True, index=False)

次にVBAです。

' 処理部分を抜き出しています。全コードは最後に記載いたします。
    With ThisWorkbook.Sheets(DATA_SHEET_NAME).Range("A1").CurrentRegion
    ' データの初期化
        Worksheets(RESULT_SHEET_NAME).Rows("2:" & CStr(.Rows.Count)).Delete
        ' ヘッダー行以下からForループを回す
        For rowNum = 1 To .Rows.Count
            ' 25歳以下かつ名前にtestを含む行を対象
            If .Cells(rowNum, "B").Value <= age And .Cells(rowNum, "A").Value Like "*test*" Then
                ' 最終行を取得
                lastRow = Worksheets(RESULT_SHEET_NAME).Cells(Rows.Count, "A").End(xlUp).Row
                ' resultシートに行データをコピー
                .Cells(rowNum, "A").Resize(, 4).Copy Worksheets(RESULT_SHEET_NAME).Cells(lastRow + 1, "A")
            End If
        Next rowNum
    End With

比較すると、Pythonは処理業が4行※1で処理が完結しているかつ、すっきりしていて可読性が高い。

一方VBAではワークシートやセルの参照方法が分かりづらく、またfor文で一致判定を行っているため行数が増えるほど処理が遅くなっていくと考えられます。

またPythonではここで取得したデータを他のライブラリを利用して分析したり、DBに登録したりなど、Excelに留まらない処理を行うことが可能です。

※1 「#」の部分はコメントのため、カウントしていない

UiPathでPython実行

Pythonでマクロと同じことが出来たとしても、それを人間が手動で実行していたら意味がありません。このコラムのメインコンテンツであるUiPathPython実行の手順をここでは紹介していきたいと思います。

実行環境

OS:Windows11
Python:3.12

導入するためにやること

  1. Pythonの導入
    1. 下記URLにアクセスし、ダウンロードボタンからインストーラーをダウンロード。赤枠のダウンロードバージョンは適宜更新されます。
      公式ダウンロードURL:https://www.python.org/downloads/


    2. インストーラーを起動し、インストール開始。
      ここでは下の「Customize installation」を選択してください。


      ここはデフォルトで問題ありません。
      「Next」をクリックし先に進んでください。


      赤枠部分を必ずチェックしてください。
      インストールフォルダにこだわりが無ければ「Install」をクリック。


      インストールが完了したら「Close」をクリックし終了。


    3. ライブラリをインストールします。Windows PowerShellを起動し、下記コマンドを実行してください。
      実行順 コマンド 内容 実行例
      1 python --version バージョン確認コマンド。
      インストールしたPythonのバージョンになっていることを確認。
      PS C:\Users\testUser> python --version
      Python 3.12.3
      2 pip install openpyxl Excelを操作するために必要なライブラリのインストール。 PS C:\Users\testUser> pip install openpyxl
      Collecting openpyxl
      Downloading openpyxl-3.1.3-py2.py3-none-any.whl.metadata (2.5 kB)
      (省略)
      Successfully installed et-xmlfile-1.1.0 openpyxl-3.1.3
      3 pip install pandas データを加工するために必要なライブラリのインストール PS C:\Users\WDAGUtilityAccount> pip install pandas
      Collecting pandas
        Downloading pandas-2.2.2-cp312-cp312-win_amd64.whl.metadata (19 kB)
      (省略)
      Successfully installed numpy-1.26.4 pandas-2.2.2 python-dateutil-2.9.0.post0 pytz-2024.1 six-1.16.0 tzdata-2024.1
  2. UiPathの準備
    1. UiPathは下記URLよりUiPathのアカウント登録後、インストーラーから手順通りに進めていくことでインストールすることが可能です。
      ※画像は手順通りのため割愛させて頂きます。
      公式URL:https://cloud.uipath.com/portal_/register?selected_language=ja 

    2. 「パッケージを管理」から、Pythonアクティビティパッケージをインストールします。


  3. UiPath側の実装
    1. MainSequence内にPythonスコープを配置します。
      Pythonはこのスコープ内でのみ実行可能です。


    2. 次にPythonスコープのプロパティの設定を行います。
      この設定で使いたいPythonのバージョンなどを指定できます。


      ターゲット x64
      タイムアウト(任意)  任意の値を設定。
      バージョン 使用したいバージョンを選択。
      今回は3.12なので、「Python >= 3.10
      パス Pythonのインストールディレクトリを指定。
      自分の環境の設定値「C:\Python312」
      デフォルトは、「C:\Users\[ユーザー名]\ AppData¥Local¥Programs¥Python\[インストールしたフォルダ]です。
      わからない場合は下記コマンドで出力された値の、python.exeより前を設定してください。
      コマンド:py --list-paths
      ライブラリパス(Linuxまたは3.9以降のバージョン) [上記のパス]\python312.dll
      自分の環境の設定値「C:\Python312\python312.dll」
    3. Pythonのアクティビティを設定していきます。
      必須アクティビティは以下です。下記の順番で設定してください。
        1. Pythonスクリプトを読み込み
          公式ドキュメント:https://docs.uipath.com/ja/activities/other/latest/developer/load-script


          コード or ファイル  「コード」にはPythonのコードをそのまま文字列として記載することが可能。
          「ファイル」には相対パスでPythonスクリプトを指定。
          結果

          読み込んだPythonスクリプトが戻り値として設定される。

          PythonObject型の変数を指定する。


        2. Pythonメソッドを呼び出し公式ドキュメント:https://docs.uipath.com/ja/activities/other/latest/developer/invoke-method


          インスタンス 「Pythonスクリプトを読み込み」の「結果」で指定したPythonObject型の変数を指定。
          入力パラメーター(任意) 関数に渡す引数を指定。
          例){“abc”, 3}
          名前 名前 Pythonスクリプト内で作成した関数名を指定。
          結果 関数の戻り値が設定される。
          PythonObject型の変数を指定。
        3. Pythonのオブジェクトを取得
          公式ドキュメント:https://docs.uipath.com/ja/activities/other/latest/developer/get-object


          TypeArgument 呼び出した関数の戻り値の型を指定。
          Pythonオブジェクト 「Pythonメソッドを呼び出し」の「結果」で指定した変数を指定。
          結果 「TypeArgument」で指定した型の値が戻り値として設定される。

           

          トラブルシューティング

           

          Q. 実行してもPythonスコープで止まってしまい、動かない場合

          A. 対応する.NETのバージョンがインストール出来ていない可能性があります。
            Windows側のログを確認し、エラーを確認してください。

          1. Windowsマーク右クリック→イベントビューアー→Windowaログ→Applivcation
          2. ログ一覧が出てくるので、レベルが「エラー」かつソース「.NET Runtime」となっているログを確認。
            赤枠に足りない.NETバージョンが記載されています。
            記載のバージョンの「.NET デスクトップランタイム」をインストールしてください。
            ,NET6.0 URL:https://dotnet.microsoft.com/ja-jp/download/dotnet/6.0

           

          Q. UiPathで出力するエラーではPythonのエラーがわからない。

          A. Python側でトレースバック出力を仕込み、それを戻り値として設定するか、エラーログファイルなどを作りそこに出力することで確認ができます。
           下記コードでは、try except構文で先程のコードをくくり、「traceback.format_exx()」関数でエラーログをmessage変数に入れています。
           

          Pythonアクティビティ導入のデメリット

          • そもそも会社によってはセキュリティの観点でPythonを導入できない環境や、外部ライブラリの利用が禁止の場合がある。
          • PCそれぞれで動かす想定等ある場合、それぞれにPythonとライブラリを導入しなければならない。(バッチで簡略化対応は可能)
          • 使用が出来ないライブラリが存在(おそらく.NET側が対応していない)

          まとめ

          VBAは今でも業務で使われる非常に有用な言語ですが、Pythonは今でも開発がされているということもあり様々な分野で応用が効き、
          また学習コストが低いため非エンジニアでも扱いやすく、汎用性が高い魅力的な言語です。
          新規で学習を始めるのならば、業務改善ツールとしても優秀なPythonをおすすめします。
          今回利用したUiPathでも今後機能が拡張されていくと思われるので、これを機にPythonに触れてみてはいかがでしょうか。
          VBAしたいな、といったお悩みがある皆さんの心に刺されば幸いです。

          インストールサポートやRPA導入なども弊社で行っておりますので、お悩み事等ありましたらお気軽にお問い合わせ下さい

          コード全文

          Python

          # -*- coding: utf-8 -*-
          ##################################################################
          ### import
          ##################################################################
          import pandas as pd # Excelからデータを取り出したり加工するライブラリ
          import traceback # エラーログを出すためのライブラリ
          
          ##################################################################
          ### 関数
          ##################################################################
          def main():
              work_path = r"C:\Users\TestUser\Desktop\work" # 作業フォルダ
              excel_file_name = f"{work_path}/column_python.xlsx" # 作業Excelファイル
              data_sheet_name = "data" # 表データがあるシート名
              result_sheet_name = "result_python" # 抽出したデータを記載するシート名
              message = ""
              age = 25 # 抽出する対象の年齢
          
              try:
                  # Excelファイルを読み込み、シートに存在する表を変数dfに設定
                  ### dfとは、pandasで作成される変数の型がDataFlame型と呼ばれるためその略称
                  df = pd.read_excel(excel_file_name, sheet_name=data_sheet_name, header=0)
          
                  # 年齢が25歳以下かつ、名前に「test」が含まれている行をフィルタリング
                  filter_df = df[(df['年齢'] <= age) & (df['名前'].str.contains("test"))]
          
                  # 既に存在するExcel内で、指定したシートに今回フィルタリングしたデータを転記
                  with pd.ExcelWriter(excel_file_name, engine="openpyxl", mode="a", if_sheet_exists="overlay") as writer:
                      filter_df.to_excel(writer, sheet_name=result_sheet_name, startrow=0, startcol=0, header=True, index=False)
                  
                  message = "正常終了"
          
              except:
                  message = traceback.format_exc()
          
              return message
          

          VBA

          Sub ボタン1_Click()
              Const DATA_SHEET_NAME = "data" ' 表データがあるシート名
              Const RESULT_SHEET_NAME = "result_VBA" ' 抽出したデータを記載するシート名
              Dim rowNum As Long ' 処理を行っている行数
              Dim age As Integer: age = 25 ' 抽出する対象の年齢
              Dim lastRow As Long ' 末尾の行数
          
              With ThisWorkbook.Sheets(DATA_SHEET_NAME).Range("A1").CurrentRegion
              ' データの初期化
                  Worksheets(RESULT_SHEET_NAME).Rows("2:" & CStr(.Rows.Count)).Delete
                  ' ヘッダー行以下からForループを回す
                  For rowNum = 1 To .Rows.Count
                      ' 25歳以下かつ名前にtestを含む行を対象
                      If .Cells(rowNum, "B").Value <= age And .Cells(rowNum, "A").Value Like "*test*" Then
                          ' 最終行を取得
                          lastRow = Worksheets(RESULT_SHEET_NAME).Cells(Rows.Count, "A").End(xlUp).Row
                          ' resultシートに行データをコピー
                          .Cells(rowNum, "A").Resize(, 4).Copy Worksheets(RESULT_SHEET_NAME).Cells(lastRow + 1, "A")
                      End If
                  Next rowNum
              End With
          End Sub
          

          関連記事

          最新情報をお届けします!

          RPAに関する最新コラムやイベント情報をメールで配信中です。
          RPA領域でお仕事されている方に役立つナレッジになりますので、ぜび登録してください!

          最新情報を受け取る方はこちら

          もっと知りたい方はこちら


          ページトップ