UiPathのREFrameworkを使ってみた　～Orchestratorのキュー機能を通してロボットを管理する～

## 初めに
RPAツールの一つであるUiPathにはフレームワークというテンプレートが数多く存在しますが、有名なもので「REFramework」というものがあります。
私自身普段は別のフレームワークを使用しているのですが、UiPath界隈で有名、かつ、汎用性が高いと聞いてましたので、ここはぜひ押さえておきたいと思いチャレンジしてみました。

今回はそのREFrameworkの中でも日本語版で、バージョンは1.3.0を使用します。


※結構説明について端折っている箇所があるので、RPAやプログラミング経験が少しある方向けだと思います。

## どのようなフレームワークか
実際にダウンロードしてこのフレームワークのワークフローを開いて実際に見てみると、UiPathOrchestrator(以下、OC)のキュー機能を使ってね！(^_-)-☆　というメッセージを感じます。
また、キューを登録するためのアクティビティが存在せず、キューを処理する側のアクティビティが用意されているフレームワークとなっています。
どんな規模でも対応できそうな点では汎用的ですが、処理の仕方は限定的かなと感じました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/5abc79b1-9baf-ac04-00e1-13dc2ae78351.png)

一見シンプルなのですが、概念を理解するという点では難しめのフレームワークになりますね。

普段私はシーケンスをメイン画面で多用するフレームワークを使用しているのですが、本フレームワークでメイン画面で使用されているのは、シーケンスでなくステートになってますね。

初見だとこれは少し厄介かもしれません。ステートというシーケンスと同じような四角のGUIから、次のステートに遷移させる為の条件を設定する必要があり、これが最初分かりにくいかもしれません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/66e7f983-07b7-6492-fd25-8fe8bd6a4615.png)

Transitionsという項目ですね。これを設定しないと実行できません。

また上部にはEntryとExitというのがありますが、Entryは入ってきたときに行う処理で、Exitは出るときに処理したいアクティビティを入れます。

大まかな流れとして、初期化で外部設定ファイル(開発現場によっては、外部変数、パラメータファイルとも言いますね)の読み取ってアプリケーションの起動を行い、OCに存在するキューアイテムを取り出し、トランザクション処理を行い、終了処理という流れになります。

もちろん、キューアイテムの取得とトランザクション処理の箇所を削除すれば、
全体的にワークフローの呼び出し前提の構造で、かつ、トライキャッチによるエラー処理は残りますので、
あとはステートマシンの仕組みが理解できれば、他のシーケンスを組み合わせたシンプルなフレームワークと同じように使えそうです。

しかしながら、どちらかというと大規模処理向けのフレームワークなのかなと感じます。


## 準備
このフレームワークを使って開発する前に、少し準備をします。

まず今回のRPA化の題材ですが、「顧客情報データcsvファイルをキューアイテムとして読み取り、トランザクション処理としてサイボウズのkintoneの顧客リストに登録していく」というものにします。

顧客リストは本物のデータを使うわけにはいきませんので、ChatGPT君にダミーデータを生成してもらいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/971e8a89-fc9c-47c1-e8e3-b836b38f3666.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/4e7b3fe2-82fa-58ed-9f1c-66ced6cd9a08.png)


AIに「すみません」なんて言っちゃってますが、こういう使い方も便利ですねー



Excelで開くとこんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/13b4356e-28d8-32a1-06aa-7f631be5994f.png)

いい感じです。

このファイルの各1行のデータを1つのトランザクションとして処理していきたいのですが、
これをOCのキューに登録する際に、1アイテムにつき必ず一意となる項目(そのデータをみればこの行のデータであると分かるユニークなもの)が必要になります。
この顧客データはぱっと見では重複している名前や会社名、住所等は無さそうなので、名前とかを一意の項目に指定してもいいのですが、やはりこの世の中には同姓同名というのがありますので、ここはIDという項目を設けて、番号を振って確実に一意にしていきましょう。

IDのカラムに関しては後で手動で列を追加して作成してます。GPTへの依頼忘れですね

## 開発
ではこのフレームワークを使って開発してみましょう。

その前にキューを扱った開発についてですが、キューを登録するロボットとキューを処理するロボットに分ける必要があります。

そうすることで、キューを登録するロボットは1台だけでもあっても、処理するロボットは複数台にして一気に処理を片付けることが可能になり、1台動かなくなっても他でカバーできたりするので、耐障害性がある体制が出来上がります。
なので、REFrameworkはキューを処理するためのアクティビティしか用意していないのだと思われます。よってキューを登録するワークフローを別で作る必要があります。

ただ、それだと面倒くさいので、このテンプレートを弄ってキューの登録も出来るようにしちゃいました(笑)



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/d3644f30-e6be-645b-77b4-b5c451e25846.png)


こちらが今回私が改造したREFrameworkとなります。


当たり前ですが、登録と処理を一度のロボット実行で行うことはしてはいけませんので、
ロボット実行時に、キューの登録なのか、キューの処理なのかを指示で分岐するようにすればいいのです。

そこで外部変数ファイルの中で、キュー登録とキュー処理でスイッチできるようになればいいと考えました。


また、外部変数ファイルですが、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/b7294bfe-7041-854c-e400-47eb5a2af0ae.png)

3行目にキュー操作切り替えという項目を設けてあり、値は入力規則で「登録」or「処理」のドロップダウンリストで2択しか選べなくなってます。


これでキュー登録時もキュー処理時も同じテンプレートが使えますね。
因みに、ロボット実行前に確認が必要ですね。　　　　　ヨシ！


この切り替え分岐は「初期化」のステートの中で行ってます。


「登録」の際は、メイン画面の右上「キューアイテム登録」に遷移して、キューアイテムをOCに追加していきます。
キューアイテムの登録箇所は以下の画像の通りです。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/fab3f71e-b58a-3619-945c-a928c46df515.png)

csvをExcelの範囲読み込みでデータテーブル化して、1行ずつ繰り返しでキューアイテムに格納していますね。

どの項目を一意にするか設定するために、キューアイテム追加のプロパティの参照の項目は以下の通り、IDとしています。
因みに、OCのフォルダーパスは、StudioがOCに接続していれば、自分のワークスペースを選択できます。
また、キュー名に関してですが、予めOCでキューの登録しておけば、それが出てきます。
キューを登録する前にOCでキューという名の器を作っておく必要があります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/8a2127c3-fca9-c901-9c3b-8170360c083f.png)

ではキューアイテムを登録してみます。ダミーデータ30件用意しましたが、多いので10件にします(苦笑)
以下、その結果です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/fcc1444f-1019-7265-4da4-63e9786d6674.png)

参照の項目がIDになってます。これが重複するとキュー登録できないので一意(ユニーク)にする必要があります。

この中から適当に3つ目のアイテムを選んで詳細を見てみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/5b4f5792-d2f6-5fda-f141-6b47942712ee.png)

しっかりとダミーデータの内容が格納されているのが確認できます。


では次にキューの処理の開発に移ってみましょう。
キューアイテムの中のデータをkintoneに登録していきます。


まず「初期化」の中で、外部変数ファイルの読み込みとアプリケーションの起動(ここではkintoneログイン)を行います。

次の遷移先の「トランザクションデータを取得」のステートですが、その中にGetTransacionDateのワークフローがあります。

ここで実際にキューアイテムをトランザクションアイテムとして取得します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/b5e6d0ce-cce6-9a0c-c176-5109248db74e.png)

OCで設定したキュー名を指定してあげて(画像ではコンフィグつまり外部変数ファイルに記載してますが、ハードコーディングでもいいかと思います。)、出力はout_Transactionitemとして、引数でメインに引き渡します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/430857cb-bd3c-895d-d04c-b0f532ed2059.png)



次に「トランザクションを処理」のステートに遷移して、そのトランザクションのアイテムをどう処理するか、ここで定義します。
今回はkintoneに登録したいので、kintoneに登録するワークフローを作成して、ワークフローを呼び出しを使って、引数で、先ほどのout_Transactionitemを引き渡します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/56c0cb22-24ab-6acd-df16-00e8e657175d.png)

out_Transactionitemはそのままだと使えないので、画像の通り"in_TransactionItem.SpecificContent"として、辞書型の変数に格納します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/b0487734-1ef8-3b1e-cb5d-e350f178033a.png)

次に、辞書型の変数に対して、会社名を抽出したいのであれば、"DirectCast(顧客情報("会社名"),string)"で抽出できます。

以下、氏名や住所等も同じようにしていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/e06d5d67-49fb-c8ed-9f2d-03e3ff586737.png)

これを10件分、トランザクションデータを取得とトランザクションを処理を行ったり来たりして、10件終わったら、
「プロセスを終了」の最終ステートに遷移して、終了処理を行う流れになります。

あとは、Config("LogMessage_GetTransactionData").ToString+TransactionNumber.ToString　等、外部変数ファイルに無い項目があったら追加してあげれば大丈夫です。

TransactionIDとかの変数について触れてませんが、使いたかったら使うみたいな感じだと個人的に思ってますので、今回特に弄ってません。

もちろん、本格的に開発するとなったら別ですが。

今回正常系のみ大まかに説明しましたが、ここまで理解出来る方なら、異常系も含め開発できるでしょう(無責任)



では実行してみましょう。
ここで忘れずに、外部変数ファイルのキューの「登録」「処理」の切り替えを忘れずにしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/a382a453-024a-0595-2cf8-8aceab5477de.png)

kintoneに入力されていってますねー
（因みに今回使用しているkintoneは30日間のお試し版です)


終了しました。
しっかり登録されてます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/31d6241f-733a-f742-9065-148458e129fa.png)

また、OCのほうですが・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/e95bb880-e2f3-04b9-9102-46be3c3b6bde.png)

ステータスが見事に全て"成功"になってます。
途中でエラーが起きた場合は、"失敗"や"処理中"となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671216/5ad12aa1-6817-5887-1e37-962348e86eae.png)

グラフも、オールクリアですね。(少々つまらない結果ですが。)

ただ、ここでしっかりビジネスエラーとアプリケーションエラーが確認出来るのはいいですね。


実際に失敗アイテムが出来てしまった場合の処理についても考察したかったのですが、また次の機会としたいと思います。

今回はREFrameworkやキュー、トランザクション処理の概念的理解と、正常系の処理を完成させただけでもヨシとしますね。

## まとめ

REFrameworkは、RPAツールやプログラミング経験が少ない方だとその理解に少々時間が必要かと思います。しかしながら、使いこなせれば比較的大きなRPAのプロジェクトにも耐え得る力は身につくんじゃないでしょうか。
(今は大規模な開発プロジェクトは減ってるかもですが、運用保守なら・・・？)

因みにキューアイテムにするデータについてですが、今回は一意をIDとしてそれに住所とか顧客情報が紐づけられる形にしましたが、一意とする項目は別にIDでなくてもいいと思います。
例えば、ファイルのフルパスをキューアイテムの一意として参照させれば、そのファイルが正常に処理されたかどうかがOC上で確認できます。
実行日時でもいいと思います。実行日時も一意ですので。

うまく使いこなして、大切なデータをしっかり管理できるものを作り上げてみたいものです。