Pythonを使ってExcelからVBAコードを引き抜く方法【GAS】

以前、Geminiを使ってExcelのVBAコードをGASに変換するツールを作成しました。Excel VBA側でコードを引き抜いて、GAS側に渡す仕組みになってるため、VBAとGASの2つの仕組みが必要になります。ただ一番スマートな仕組みでもあります。

しかしVBAコードを引き抜く部分をクラウド側で実現出来たら、VBA側での仕組みが不要になるのでなんとか出来ないかなぁと思い調べてみた所、Pythonで実現出来そうなので、GCPを利用しつつ実現してみました。

Geminiを使ってVBAからGoogle Apps Scriptに変換する仕組みを作る【GAS】

今回利用するツール等

oletoolsはローカルで動作するPythonを使ってVBAのコードを引き抜くツールです。今回、Cloud Run Functionsで利用するのでGCP上で動作させます。合わせて、xlsmファイルを渡す必要がある為、Cloud Storageへのアップロードも必要になります。

以下の2つの内容も併用することになるため、先に閲覧していただければと思います。

Google Apps ScriptでCloud Run Functionsを操作する【GAS】

Google Apps ScriptでCloud Storageにファイルをアップする【GAS】

事前準備

GCP上の準備

APIの有効化

今回はGCP側のGoogle Cloud Storage JSON APIを利用してファイルをアップロードします。

  1. GCPのAPI とサービスの画面を開く
  2. APIとサービスを有効にするをクリックする
  3. cloud storageで検索すると出てくる「Google Cloud Storage JSON API」を見つけてクリック
  4. 有効化をクリックする

図:Cloud Storage JSON APIを有効化する

サービスアカウントの作成

Cloud Run FunctionsやCloud StorageをAPI経由で操作する場合に利用するサービスアカウントを用意します。このサービスアカウントはGCSおよびGCF両方で利用します。

  1. GCPの左サイドバーからIAMと管理を開く
  2. サービスアカウントを開く
  3. サービスアカウントを作成をクリックし、サービスアカウントの名前を入力。わかりやすい名前をつけましょう。キーのタイプはJSONを選択
  4. サービスアカウントの役割では、今回はとりあえず編集者にしましたが、本来はより小さいロールに絞る必要があります。
  5. 作成が完了したら、作ったサービスアカウントをクリックして中に入る
  6. 上部にある「鍵」をクリックする
  7. キーを追加をクリックし、新しい鍵を作成をクリックする
  8. JSONのまま作成をクリックする
  9. JSONファイルが自動でダウンロードされる
  10. JSONファイルがダウンロードされるので、これを誰とも共有しない形で、Google Driveにアップロードします。流出すると後で課金で痛い目を見るので絶対に共有はしないでください。
  11. アップロードしたJSONファイルのIDを取得する
  12. 次の項目のJSONキーファイルを取得して認証するにて、冒頭の変数keyfileの場所にこのIDを入れてあげる。
  13. このアカウント名も控えて於いて、後でCloud Storageのアクセス権限に追加します。

最後にこのサービスアカウントのメアドを控えておきます。あとでGCSでの設定で利用します。

図:このキーファイルが重要です

GAS側の準備

ライブラリの追加

OAuth2.0認証をする為のライブラリを追加します。以下の手順でスクリプトに追加する必要があります。

  1. スクリプトエディタを開く
  2. 左サイドバーのライブラリの横にある+アイコンをクリックする
  3. ライブラリを追加欄に「1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF」を追加します。
  4. バージョンは最新版を選んでおきます。
  5. 追加をクリックする

これでサービスアカウントの認証に利用します。

図:ライブラリを追加する

プロジェクトの移動

サービスアカウントを利用して認証を行いますが、GCP側のAPIを利用する為、GASのプロジェクトをGCPのプロジェクトに紐付けする必要性があります。連結する手順は以下の通り。

  1. Google Cloud Consoleを開く
  2. 左上にある▼をクリックする
  3. ダイアログが出てくるので、新規プロジェクトを作るか?既存のプロジェクトを選択する。この時、G Suiteであれば選択元は「自分のドメイン」を選択する必要があります。
  4. プロジェクト情報パネルから「プロジェクト番号」をコピーする
  5. 対象のGoogle Apps Scriptのスクリプトエディタを開く
  6. 左サイドバーのプロジェクト設定を開く
  7. Google Cloud Platform(GCP)プロジェクトのところまで移動する
  8. 4.で入手した番号をプロジェクトを変更のテキストボックスに入れて、プロジェクトを設定ボタンをクリックする
  9. 無事に移動が完了すればメッセージが表示されます。

図:プロジェクト番号が必要

図:GAS側でプロジェクト紐付け

Cloud Run Functions

今回、Cloud Run FunctionsではいつものNode.jsではなくPythonを利用します。その為の準備をしておきます。

環境の準備

事前にサービスアカウントの作成が必要になりますが、今回はデフォルトで用意されてるサービスアカウントをそのまま利用します。GCPの画面を開いて作業を開始します。

  1. 右上のハンバーガーメニュー(≡)をクリックし、サーバーレス項目にあるCloud Runをクリック
  2. 上部にある「関数を作成」をクリックする
  3. インライン エディタで関数を作成するの選択状態のままにする
  4. サービス名には適当な名前を入れます(今回はvbaconertとして入力しました)
  5. エンドポイントURLが出ているのでコピーする(例:https://vbaconvert-xxxxx.us-central1.run.app)
  6. ランタイムはPython3.9をとりあえず今回は選んでいます。
  7. 未認証の呼び出しを許可に今回はチェックを入れる(認証を要する場合には別途認証を用意する必要があります)。デフォルトではHTTPトリガーは認証を要するので、第一世代パターンでの未認証の場合にはこちらの手順も見ておきましょう。
  8. トリガーは省略します
  9. 今回はテストなのでコンテナの設定に於いて、リソースでは、メモリ256MB, CPUは1で設定します。
  10. 続けて実行環境に於いては第2世代を選択します。
  11. セキュリティタブでは作成しておいたサービスアカウントを選択します(今回はデフォルトのまま)
  12. 作成をクリックする
  13. Cloud Build APIを有効にしろと出てくるので、有効にするをクリックする
  14. するとrequirements.txtやmain.pyの記述画面が表示されるようになる。

さて、この状態ではサービスアカウントを指定していないので、以下の作業を追加で行います。

  1. 作成したGCFの中に入り、上部にある「新しいリビジョンの編集とデプロイ」をクリックします。
  2. セキュリティタブを開く
  3. サービスアカウントの欄があるので、ここで前述で作成しておいたサービスアカウントに変更しておきます。
  4. デプロイをクリックして保存する

これでこのGCFについては、指定のサービスアカウントで動かすという規定ができました。

図:Cloud Run FunctionsでPythonを使う

図:作成済みサービスアカウントに変更しておく

Google Cloud Consoleを弄ってみる

requirements.txtの記述

用意したGCFのPython実行環境のソースを開くと、左サイドバーに「requirements.txt」という項目があります。Node.jsで言うところのpackage.jsonみたいな存在でここに利用するライブラリを登録します。今回はCloud Storageとoletoolsの2つを利用しますが、最初から登録されてる項目を消さずに追記で登録します。

最後に保存して再デプロイをクリックして完了です。

図:利用するライブラリを登録しましょう

ローカル開発環境の用意

以下はmacOSの場合の環境構築ですが、GCF上でソースコードを書いてデバッグはちょっとやりにくいので、ローカル環境である程度動かせるコードにしてからGCF上にコードを貼り付けたほうが生産的です。Homebrewが事前にインストール済みである必要があります。

Homebrewでpipxを入れてから、pipxを使って入れると目的のコマンドをインストールすることが可能です。oletoolsとgoogle-cloud-sdkが必要になります。

Cloud Storage

GCF側からExcelファイルにアクセスする為には、Cloud Storageのバケット内にファイルが存在している必要があります。よって、GAS側からアップロードする先として入れ物を用意しておく必要があります。以下の手順でバケットを用意して、アップロード用コードの為のバケット名を取得しておきます。

  1. Cloud Consoleにて、Cloud Storageを開き、バケットの作成をクリック
  2. 名前に半角英数字で命名する。これがバケット名になる。(今回はdriveman_gsという名前にしました)
  3. 作成をクリックして完了
  4. 今回は更に、publicという名前のフォルダを用意しました。
  5. 作成したGCSの中に入る(バケットの詳細)
  6. 上部にある「権限」をクリックする
  7. アクセス制御が「均一: 有効なオブジェクト レベルの ACL がない」となってるので、きめ細かい管理に切り替えるをクリックする
  8. きめ細かい管理にチェックを入れて、保存をクリックする
  9. GCSの詳細に戻ってきたら、アクセスを許可をクリックする
  10. サービスアカウントで控えておいたサービスアカウントのメアドを新しいプリンシパルに入れる
  11. ロールは「ストレージオブジェクト作成者」を割り当てます
  12. 保存をクリックする

よって、バケット名driveman_gsとpublic以下にファイルをアップするので、ファイル名としてはpublic/hoge.xlsmという形になりますので、控えておきましょう。

図:この名前があとで重要になります

図:きめ細かい管理とする

図:サービスアカウントを権限として追加

ソースコード

GCF側のコード

GCFに対して、「extract_vba」という名前の関数を用意しました。そして、その中に以下の仕様でGAS側からのリクエストに対してコードを引き抜いて返すコードを記述しています。

  • bucket名とファイルのパスを受け取る。
  • VBAの標準モジュールに於いて、「Module」と名前がついてるファイルについてだけ抜き出し対象とする。
  • 対象となったコードをvba_codesに加えて最後にGAS側へと返す。
  • GAS側に返す前にCloud Storageにアップされたファイルを削除する

GAS側のコード

サービスアカウント認証

authorize.gsの中に以下のコードを記述しました。keyfileにはサービスアカウントのJSONキーファイルのファイルIDを入れて、startoauthを実行すると認証が完了しダイアログが出ます。ユーザの認証ではないのでこれで完了です。

GCSへアップロード

Google Drive上にアップされたVBA入りのExcelファイル(xlsmファイル)について、Cloud Storageの該当の場所にアップロードするコードです。昔に書いたものより若干変わってる場所があります。

  • methodは「PUT」を指定します。
  • リクエストの内容にhostという項目が増えているので、これを追加する
  • gcsurlのリクエストエンドポイントが以前のコードとはちょっとURLが変わっていますので注意。

無事に動くと指定のバケットのpublicフォルダ以下に対してファイルがアップロードされます。

GCFへリクエスト

ファイルのアップロードが完了したら、次にGCFに用意した関数を実行して、コードを引き抜く為のリクエストをします。

  • bucketとfilenameの指定が必要です。これをpayloadに加えてリクエストを投げます。filenameは「public/hoge.xlsm」といった形で指定します。
  • methodは「POST」でリクエストを送ります(上記のpayloadがあるため)
  • レスポンスには引き抜いたVBAコードが返ってきますので、これをさらにGeminiに投げるなどしてGASのコードに変換するであったり、ファイル化してドライブに保存することが可能です。

関連リンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)