SAP GUI Scriptingで自動操縦してみた

自身の業務で、SAPを使う機会があったのですが、そもそもこのSAP、標準でSAP上の操作をExcelのマクロ機能のように録画し、再生するという機能である「SAP GUI Scripting」という機能が備わっています。よって、誰でも簡単に操作を記録して、しかも記録内容はVBSファイルで出力されるので、加工し、Excel VBAなどに組み込んで利用可能であるため、非常に汎用性が高い。

RPAでわざわざSAPの操作を記録してなんてやるよりも、直接VBAからExcelのデータを送り込んだり、エクスポートさせたものを取り込んで整形⇒Teamsに通知なんてことをVBAで仕込めるので、どこぞの超高額RPAなんて要らないのではないかと思います。

今回使用するアプリ

  • SAP GUI

今回は、VBAなどを使って操縦し加工する手前までの単純にクエリの出力までを装備するものになりますので、SAP GUI以外は不要です。ちなみに、公式では昔からRFCにVBSから接続して処理するといったサンプルが出てたりと、割と自動化を結構前から装備できる仕組みが用意されていたりします。

SAP標準機能なので、この機能の為の追加支払いコストはありません。また、実行もWindows標準機能のVBSで動かしてるので、追加セットアップも必要ありません

VBScriptの非推奨化

2023年10月10日、MicrosoftからVBScriptの非推奨化と将来的なWindowsからの機能削除が発表されました。長年に渡って利用されてきたVBScriptですが、これにてDeprecatedが発表されたことで様々な領域への影響が非常に大きいと思われます。VB構文で書けて、情シスでも自動化の1つの選択肢として使ってきたり、デスクトップ自動化でもCOM経由で操縦できるVBScriptは非常に便利でした。

そして、この影響はVBScriptで自動操縦を行ってるSAP GUI Scriptingにも及ぶ為、今後どうなるのか?PowerShellに書き換えが必要ですが、ちょっと普通のユーザで出来ることじゃないので、SAP側が抜本的な変更を迫られることになるかと思います。

事前準備

事前準備といってもおそらく標準で使えるようになっているので、その確認作業になります。

  1. SAP GUIを起動する
  2. 左上のハンバーガーメニュー(≡)をクリックして、オプションを開く
  3. 左のメニューの「アクセシビリティ&スクリプト」を開く
  4. さらにスクリプトを開く
  5. 右側のパネルの「スクリプト有効化」にチェックが入ってることを確認します。
  6. スクリプト有効化以外の「通知」などのチェックは全て外します
  7. サイドバーからセキュリティを開く
  8. セキュリティ設定を開いて、無効化します。
  9. チェックしたら、適用⇒OKをクリックして閉じる

図:有効化していればすぐ使えます。

図:セキュリティ設定は無効化します。

使ってみる

操作を記録する

操作の記録をするためには、まずSAP GUIにログインしておきます。ログインが完了したら、以下の手順で操作を記録していきます。Excelのマクロの記録と同じ感覚でVBSファイルが出来上がります。

  1. ツールバーの歯車(⚙)アイコンをクリックする
  2. スクリプト記録と再生という項目があるので、クリックする
  3. 記録と再生という小さなツールボックスが出てくるので、「追加」をクリックする
  4. 保存先の[...]をクリックして、VBSファイルの出力先を指定します(ファイル名であるxxx.vbsまでしっかり指定が必要)。動かない事があるので、その場合は直接パスを入力
  5. 」をクリックすると記録開始。「」をクリックで停止。「」で再生されるようになっています。
  6. 記録開始したら、あとは普通に操作する。但し無駄な動作も全部記録されてしまうので、いつもより慎重に一個ずつ丁寧に操作します。
  7. 記録が完了したら、「」をクリックすれば、VBSファイルが出力されているはずです。

図:録画ツールを出す為のメニュー項目

図:ツールボックスの表示

自動化を実行する

きちんと丁寧に記録したものであれば、SAP GUIにログインした状態で、出力されたxxxx.vbsファイルをダブルクリックするだけで、自動実行が開始されます。非常に高速で実行されるので、RPAよりもはるかに早く処理が終わると思います。

ただし、Excel出力した時に閉じる動作などを記録してしまうと、時々リモートプロシージャコールの失敗でエラーになったりしますが、そこだけ注意すれば、例えばデータを

  • Excel形式ではなくタブ区切りファイルでローカル出力
  • 出力されたものをExcel VBAでインポート処理
  • また、画面下部からは直接xlsx形式での出力オプションも用意されています。

といった形で、Excel形式にする事が可能になると思います。標準ではドキュメントフォルダ\SAP GUI\以下にファイルが保存されるようになっています。自動実行時に例えばBoxのフォルダ内にファイルを作ろうとすると、SAP GUI セキュリティの画面が出てきます。これは自動化記録が出来ないので、もし問題がなければ、事前準備でも使った設定の中にあるセキュリティ通知を無効にすると出てこなくなります。

図:SAP GUIセキュリティ通知を無効にする

図:問題のセキュリティ通知ポップアップ

VBSファイルの中身を見てみる

実際に生成されたvbsファイルの中身を見てみると以下のようなコードになっています。現場で使う上でこれだけでは足りないので、ファイル名や保存先フルパスなどを足してコードを改造してあります。

  • findByIdがSAP GUIの各パーツのSAPIDを探してアクションをしてるものになります。
  • 見た目はなんとなく、UIAutomationに似ていますが、SAP GUI操作をする独自のものになります。
  • Excel形式での保存先、またその時のファイル名はyyyyMMddhhmmss形式のファイル名としてBoxの所定のフォルダに保存するよう改造してあります。
  • Boxの場合ログオンユーザ名毎に所定のフォルダが変わるので、ログオンユーザ名を取得して動的にフルパスを生成しています。

他のアドホッククエリなどで日付の指定などを外部からパラメータで送りたい場合には、VBSにてインプットボックスを表示して入れてもらうか?また、Excel VBAなどから直接vbsファイルを呼び出す時に、引数でVBAに渡して利用するなどの工夫が必要になります。

特定のクエリを確実に実行する方法

特定のユーザグループにアドホッククエリを追加していくと、当然ながら順番などがズレます。しかし、SAP GUI Scriptingで生成されるVBSでこれらのクエリの実行は、特定の名称でヒットさせているのではなく、単純に何番目のクエリという形で実行させているので、このままでは「クエリを追加したり削除した場合」に実行対象のクエリの位置がズレてしまうことになります。

そこで、この解決法を探した所、SAPコミュニティに同様の事例の投稿があり、そちらのコードを修正して使うことにしました。

  • クエリ一覧のダイアログが出てから、クエリ選択・実行までのコードです
  • クエリの名称と一致するものを1個ずつグリッドに表示されてる名称と一致するか?検証しては1個スクロールさせています。
  • 一致したらループを抜ける。そのため、検証中にcounterを回しておきます。
  • クエリの選択はgetAbsoluteRowにてcounterの値を指定し、Selectedで選択させることが可能です。
  • ボタンをクリックさせて、クエリが実行されます。
  • wnd[1]/usr/tblSAPLAQ_INT_FUNCTIONSTCH_OPEN_QUERIES」の部分は、SAP GUI Scriptingで生成させたときに出てくるので、それを利用します。環境によって変わるので注意。

このグリッドがちょっと変わった仕様で、1度に表示できるのが10個まで、次の10個はスクロールさせないと値が取れない仕組み。10個ずつでスクロールさせてもうまく取得が出来なかったのですが、1つとって1スクロールだとクエリ名が問題なく取得が出来たので、常にスクロールさせた一番上のクエリを取る仕組みになっています。

図:名称の部分でヒットさせて行番号を取得するのがポイント

Excel VBAから呼び出す

ソースコードの移植

元々のコードがVBSである為、VBAに移植するのは実は非常に簡単です。Public Functionを用意して、基本的にはコピペ。必要な変数の宣言を追加するくらいで動いてしまいます(参照設定等は必要ありません)

以下はVBAの場合のコードになります。

  • WScript.ConnectObjectの部分は必要無いのでコメントアウト
  • 冒頭にVBSでは無かった変数の宣言を追加します。
  • ログオンユーザの取得は、CreateObject("WScript.Network")に変更してるだけ。
  • あとはVBSコードをそのままコピペしてる

よって、Excel VBAから実行させる場合には、VBAからシート内のデータにアクセスしてそれをコードに簡単に渡せるので、VBSよりも更に利便性がアップします。また、設定関係のGUIなどを別途フォームで用意も出来たりするので、iniファイルに予め保存しておいたり(例えば、出力先など)をコードを弄らず変更可能に出来たりするので、オススメです。SAP GUI Scripting単体ではSAPしか操作出来ませんが、VBAからならば、色々自動化に繋げられるので、以下のエントリーも参考にしましょう。

VBAで他のアプリケーションを操作する

SAP GUIの起動~ログインまで自動化

SAP GUI Scriptingはログイン自体の自動化もできるようになっています。しかし、ログイン前の接続先の選択等でログオンボタンを押す部分には手が出せないので、ここをVBAのSendkeyを使って処理をすることで自動起動⇒自動接続⇒自動ログオンが実現できます。パスワードの保全だけ何か安全な手法で暗号化復号化が必要にはなると思います。

また、この時スクリプトの実行時にメッセージが出るのが鬱陶しいので、スクリプト通知はオプション設定からオフにしておきましょう。

  • 自分の場合、接続先が一番上にあるので、Enterキーを送るだけでログオン画面に行けるので、Enterキーだけ送っています。異なる場合は、TABや方向キーなどを送りつけて、接続先を選択するようにすると良いでしょう。
  • 起動すぐにキーを送ると、まだ起動していないのにキーが送信されてしまうので、Sleepで5秒間ウェイトを掛けています
  • 省略以下は前述の処理と同じ。通知メッセージを切ってるので、自動処理が完了するまであとは一直線です。
  • ユーザIDとパスワードを直書きでVBAコード内に入れるのはやめましょう。暗号化・復号化を別に装備したり、資格情報マネージャから取り出すなどの装備が別途必要です。

図:スクリプト実行時の通知はオフにしておく

資格情報マネージャ読み書きプログラムをNode.jsで作成する

Electronから呼び出す

現在、これら作成したVBSファイルを管理(渡すパラメータや時限発火させる日時など)する為のプログラムを作成中ですが、以前も紹介したテクニックを応用して、Electron + Node-Cronを利用して指定時刻に自動実行するように構築しています(既にプログラムは概ね完成)。

今回のVBSは引数を取得してSAPを自動操縦するようにしている為、これらをうまく同期的に処理させないとマズイので、工夫が必要です。

VBSと連携するElectronアプリを作る

図:管理用プログラムがあれば尚便利になる

Node.js側コード

  • SAPのパスワードは資格情報マネージャに格納しているので、keytarを利用して読み書きを行っています。
  • 呼び出し前にsapcheck関数で、SAPが起動してるかどうかを確認し、していなければ起動させてログオンしてから次の処理に渡しています。
  • 引数はカンマ区切りでcmdargsに格納し、vbsのファイルへと渡しています。
  • VBS側からのstatusの返り値を取得してから次の処理へと移っています。

VBS側コード

自動起動させるVBS

  • 引数はIDとPWをカンマ区切りで受け取り、VBS側で分解して利用しています。
  • SAPを操作できるのはログオン画面以降からなので、最初のログオンボタンを押す部分については、ウィンドウをアクティブにしてからSendkeysでキーを送って次に進んでいます
  • saplogon.exeが起動してるかしていないかで、起動チェックを掛けています。
  • 無事に起動済みになったら、statusは3を返します。起動失敗時には1を返します。
メインのSAP操作用VBS

最後に勝手に起動するExcelを終了させる為のコマンドはこちらのサイトからお借りしています。

  • VBSで処理に必要な引数は1個の固まりとして受け取っています(カンマ区切りで取得)。コレを分解して利用します。
  • 保存先フォルダはログインユーザ名毎に違うので動的にフルパスを生成しています。
  • 処理が成功したらstatusは3を返し、Node.js側で次の処理を実行します。エラーの場合1を返し、処理を停止します。
  • 最後に自動で開かれるExcelファイルをTerminateProcessにてすべて閉じてしまいます。

TerminateProcessの場合だと、他に作業していたExcelまで含めて全て閉じられてしまうのはExcelは1プロセスで複数ブックを処理してる関係でプロセスが独立していないのが、原因。この問題の対応策として、ExcelのプロセスをKillするのではなく、開いてるブックを調べてブックを閉じるだけの処理にすること(その為、空のExcelのプロセスは残る)

その場合は、以下の関数をVBSに追加して、TerminateProcess("Excel.exe")をTerminateWorkbook(filename)に置き換えることで実現可能です。

  • 既存のExcelプロセスが起動していないと、GetObjectでエラーになるので注意
  • bk.closeしてるだけなのでプロセスは残ります
  • ファイル名が一致する場合だけ閉じます(Excelは仕様上、違う場所にある同じファイル名のファイルでも起動は出来ない為)
テーブル化する

前述までのコードの場合、単純に出力したExcelファイルを保存しているだけですが、以下のコードを追加する事で範囲をテーブル化する事が可能です。TerminateProcess("EXCEL.EXE")の後に追加します。

以上のコードでVBSからExcelブックを操作しテーブル化していますが、もしここからコピペをしているようなケースがある場合には

  • ファイル名を固定化し、コピペではなく貼付け先のExcelファイルから今回出力したExcelファイルのテーブルを参照するようにする
  • テーブルを参照は、Power Queryを利用して実現することが可能です。
  • 出力ファイル名を固定化するので、事前に同じファイル名のファイルがある場合には削除する、存在確認をするコードを更に追加すると良いでしょう

Excelで身に付けるべきスキルコース(松)

Power Automate Desktopから操縦する

SAP GUI Scriptingは、SAP上の操作に関しては一部を除いてほぼ完璧に再現出来ます。しかし、以下のような限界点があります。

  1. 固定的なパラメータによる自動化は完璧でも、動的なパラメータによる自動化は管理プログラムのようなものが必要になる(アドホッククエリのパラメータを実行時毎に異なるものにしたい等)
  2. ログオン画面から先は自動化できるが、ログオン自体の自動化は出来ない
  3. Excelデータを元にループで回してSAPを操作するには、結局VBSのコードを大幅に改造する必要がある
  4. SAP操作後の処理については管轄外であるので、本当にSAPの操作のみしか自動化出来ない
  5. 時限発火させる為には、バッチファイルとVBSをタスクスケジューラ等を利用して登録する作業が必要になる

故に、自分は管理プログラムを作ってるわけなのですが、単純な操作の自動化だけを実現しても正直あまり時間短縮の効果はありません。ということで、管理する部分をPower Automate Desktopで作ったらどうなるか?試してみました。

Power Automate Desktopの問題点

SAP GUI Scriptingを使わずに全部をPower Automate Desktopの「デスクトップレコーダ」を使って記録してしまえばいいじゃないか?という人がいるでしょう。しかし実際に作ってみればわかりますが、とりわけSAP上の操作では

  • ダブルクリックの認識がシングルクリックで記録されていたりする
  • 画面UI要素の認識が非常にモッサリしていて、記録が取りこぼされているケースも多々ある
  • ウェイトを意識的に入れないと、要素の操作に失敗する事も結構ある
  • とある要素に至っては赤枠が出ず認識しないケースもあった(Excelでのエクスポートをするボタン等)
  • デスクトップレコーダ自体が相当重いので事務用PCではキツイケースがある(マウスカーソルかくかく)

正直、正確さとスピードに関してはPADで記録するより、SAP GUI Scriptingで記録したほうが、ストレスも無くいちいち認識待ちなど必要無いので、Power Automate Desktop自体でデスクトップレコーダを使ったUI操作はオススメしません。

PADが担当する部分は操作のアシスト

前述の通り、PADが担当するのはSAP GUI Scriptingでは実現出来ない部分の自動化を構築するために利用します。例えば

  • SAP GUIに自動ログオンする
  • SAP GUI Scriptingで用意したVBSの「出力ファイル名」であったり、「パラメータ」部分をPADで都度変更して渡して実行する
  • 繰り返し登録するような「ループ処理」で同じ処理を登録したVBSに何回も作業を投げて回す
  • SAPでファイル出力後以降の、そのファイルに対しての操作を継続して自動化する部分

実際に作ってみる

自動ログイン⇒VBS実行⇒結果を取得までの流れを作っています。ただしいくつかの注意点があります。

  • 冒頭のSAPへの自動ログインはデスクトップレコーダでログインボタンを押す場所までを作成します。
  • ログイン画面以降のIDおよびPWの入力も今回はデスクトップレコーダで作成しています。パスワード類は別の安全に取得できる手段を構築する必要があります。
  • UI要素のRSYST-BNAMEがログインID、RSYST-BCODEがパスワードの入力欄になります。
  • PADのVBScriptを実行アクションは簡単なVBSしか実行出来ないので、今回は前述のElectronで呼び出す場合のVBSファイルを別途用意しておきます。
  • VBSファイルへのフルパス(vbsfile)、出力するファイル名(filename)、出力先フォルダのフルパス(exportpath)をそれぞれPAD上で変数で設定しておきます。
  • コマンドラインを変数の中で構築します。今回は

    といった形で構築しています。//nologオプションを入れておかないと、VBSの出力結果(返り値)にcscriptのバージョン情報やcopyrightが入ってしまうので必ず入れておきます。
  • VBSからは無事操作が完了したら、3が返ってくるように一番最後に「WScript.StdOut.WriteLine status」で出力するようにVBS側を修正しています。
  • DOSコマンドを実行アクションで、構築したコマンドラインを実行します。
  • 返り値はCommandOutputで受け取り、メッセージボックスで表示するようにしています。ここで条件分岐やループの次の処理などを組み込んでいくと良いでしょう。

一番のポイントは、標準のVBScriptを実行アクションが使えない点。故にDOSコマンドにてcscript.exeを叩く点です。SAPの起動チェック等も前述のVBSを叩いて処理しても良いでしょう。

図:こんな感じのフローになります。

考察

メンテナンス面での優位性

日本では、本場ドイツやグローバル企業とは異なり、とかく複雑なアドオンを鬼のように開発してSAPに組み込み魔改造する傾向があるというお話を伺ったことがあります。しかも人事給与計算だけでなく他の領域でもかなりの費用と時間を掛けて。

しかし、SAPでも最近ありましたが大型メジャーアップデート時にこれらのアドオンが一斉に動かなくなる可能性もあります。また、平時であってもこれらのメンテナンスコスト(内製であれ外注であれ)馬鹿にならない費用が固定費として経営にのしかかって来ることになります。

これらのうち、わざわざアドオンで作らなくてもいいでしょ?という類のものは、こうしたツールで外側で作っておくほうが、バージョンアップ後でも最低限の修正で済む(SAPと直接連携してるわけじゃなくただ操作を再現してるだけなので)ので、コスト面では圧倒的に優位になります。

自動化の優位性

VBSで出力されるという事は、以下のメリットがあります

  • VBAと殆ど同じ文法なので、誰でも簡単に改造する事が可能になる
  • VBSで動かしてるので、非常に高速に動作する上に事前セットアップなどが必要ない(標準でWindowsでは使える為)
  • VBSというWindows標準機能で自動化を実現しているので、特定RPA製品にベンダーロックインされたり、製品が消えて困ったという事がなくなる
  • 当然、外部RPAを使わず実現できるので、ライセンス費用や専用マシンなんてものは必要なくなる
  • VBSなので、Power Automate Desktopから叩くという形で、Windows標準のRPAをあえて使うという選択も可能になる
  • VBSなので色々な知見やソースコードのサンプルが沢山公開されており、学習コストを低くすることができる。
  • Excel VBAやコマンドライン、さらにはNode.jsなどから引数を渡して叩く事ができるので、本体側で自動化の装備をする必要がない。
  • VBSはVBA同様、Outlookなどのコンポーネントと連携できるので、かなり簡単に上記のコードにメール送信などが追加できる。
  • 操作の記録自体はとっても簡単なので、誰でも自動化スクリプトを生成できる(複雑なものはVBS編集が必要だけれど)
  • マウス操作やキー送信でSAP GUIを操作していないので、ユーザが自動操縦中になんらかの操作をしても影響を受けない。
  • SAP GUI Scripting自体結構歴史があって、利用されてきた実績がある(2010年頃のSAP 6.20から使えているようです)。

関連リンク

コメントを残す

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

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