皆さん初めまして。
システムズエンジニアリングセンター(SEC)の李と申します。

 

今回はスクリプト言語、Java等の他言語経験者が初めてUiPath Studioの開発を行う上で、戸惑ってしまうであろう「ワークフローファイルを呼び出し」アクティビティを使用した引数の扱い方を紹介したいと思います!

目次

「ワークフローファイルを呼び出し」アクティビティとは

「ワークフローファイルを呼び出し」アクティビティとは、一連の処理の塊をまとめた別のワークフローファイルを呼び出す部品です。ワークフロー全体の処理量が多くなっても、ファイルを分割することで、可読性や保守性を向上することができ、業務用のワークフロー開発では使用する頻度の高いアクティビティです。
呼び出し元のワークフローと呼び出し先のワークフロー間のデータの受け渡しは引数(ひきすう)と呼ばれる機能を使用します。

関数呼び出しに似ている特性のため、ある程度プログラミングに慣れていた筆者としては感覚的に関数名と引数を設定すればすぐ実装できるものだと思いました。しかし、実際は引数の設定がうまくいかずに2,3時間ハマってしまいました。
Web上で調べてもどの入出力設定だとどうなるかを簡潔に書かれているサイトなどが無かったため、いろんなパターンを試行錯誤してやっと法則を理解しました。

ここではUiPath Studio初心者がみんな(たぶん)躓くと思われる引数の入出力設定をまとめた内容を解説していきます。蓋を開けてみればなんてことはない内容なので、初めてUiPath Studioでの開発を行っていて同じような所で困っている人の助けになればと思います。

引数の設定方法

筆者のハマったポイントを説明する前に、この章では引数の設定方法と各項目の概要を説明します。

まずは引数を設定するときの正しい手順を説明します。ここを理解していなかったために筆者は苦労することとなりました。

①呼び出し先ワークフローの引数パネルにて引数を設定
②呼び出し元ワークフロー内の「ワークフローファイルを呼び出し」アクティビティの「引数をインポート」ボタンをクリック
③インポートした設定内容の確認
④「値」列を記入して「OK」ボタンをクリック

続いて各手順の詳細な内容を実際の操作画面と一緒に説明します。

①呼び出し先ワークフローの引数パネルにて引数を設定
以下の図1に示すように呼び出し先ワークフローの「引数」パネルをクリックします。

図1:呼び出し先ワークフローの画面
拡大
図1:呼び出し先ワークフローの画面

引数パネルを開くと図2のようなウィンドウが出てくるのでここで引数の設定を行います。

図2: 引数パネルの設定画面
拡大
図2: 引数パネルの設定画面

以下の表2に各設定項目の概要をまとめました。

表1:引数パネルの設定項目まとめ
拡大
表1:引数パネルの設定項目まとめ

②呼び出し元ワークフロー内の「ワークフローファイルを呼び出し」アクティビティの「引数をインポート」ボタンをクリック
以下の図2に示したように「ワークフローファイルを呼び出し」アクティビティの「引数をインポート」ボタンをクリックします。

図3:「ワークフローを呼び出し」アクティビティ画面
拡大
図3:「ワークフローを呼び出し」アクティビティ画面

③インポートした設定内容の確認
下記の図3で示すように手順①で設定した引数情報が「名前」、「方向」、「型」の項目にインポートされていることを確認します。

図4: 引数をインポートの設定画面
拡大
図4: 引数をインポートの設定画面

④「値」列を記入して「OK」ボタンをクリック
「値」列には下記図5のように「入力」であれば受け渡す値、もしくは値を格納した変数名を、「出力」には値を受け取る変数名を、「入力/出力」には受け渡す値を格納していてさらに出力を受け取る変数名を設定します。

図5:インポートの設定画面に変数設定後画面
拡大
図5:インポートの設定画面に変数設定後画面

以上が引数の設定方法となります。
※注意点:「名前」、「方向」、「型」の項目が呼び出し元(ワークフローファイルを呼び出しアクティビティ)と呼び出し先ワークフローで一致していないと引数の受け渡しが成立しません。←筆者は自由に「名前」を設定したので躓きました。

筆者がハマったポイント

この章では前章での引数の設定方法を知らなかった筆者がどのようなポイントで引数の設定にはまってしまったかご紹介したいと思います。
※この章は筆者が以下に引数設定で躓いてしまったかを解説しているだけなので読み飛ばしても大丈夫です。

以下に筆者が「ワークフローを呼び出し」アクティビティをスクリプト言語などの関数を呼び出すイメージの機能だと思ってしまっていたためにハマってしまったポイントを解説します。

ポイント①:設定項目「名前」を呼び出し元と呼び出し先で合わせなくてはいけないこと
筆者の見慣れた言語では「関数名(変数1,変数2)」が基本的な関数の呼び出し方であり、呼び出し元と先で使用する変数名が違っていても構いませんでした。(慣れていた言語では左から何番目の引数という順番で変数を対応付けしてくれる言語だったため。)
こういった理由で、特に意識せずに引数の設定項目「名前」を呼び出し元と呼び出し先でそれぞれ別名として設定していました。そのため「名前」が呼び出し元と呼び出し先で異なっているため、引数の受け渡しができない状況に陥ってしまい理解するのに時間がかかってしまいました。ちなみに引数の名前を合わせることで引数の受け渡しを行う言語仕様自体は珍しいことではないらしく、まだまだ勉強が足りないなと実感しました。

以下に名前不一致による引数の受け渡し失敗例を示します。

図6:名前不一致による引数受け渡し失敗例
拡大
図6:名前不一致による引数受け渡し失敗例

ポイント②:設定項目の「方向」が「出力」のみの場合の変数初期化を行う正しい場所
2つ目に躓いてしまったポイントは引数の方向が「出力」のみの場合、配列型など変数の初期化が必要な型は初期化処理を呼び出し先ワークフローで実施する必要があるということです。
引数の方向が「出力」のみの場合、方向に「入力」が含まれていないため呼び出し先ワークフローは呼び出し元ワークフローから何も受け取っていない状態となります。
呼び出し元ワークフローで初期化処理を行っていたとしても、その変数が受け渡される訳ではないため呼び出し先ワークフローでそのまま「名前」変数に値を代入しようとしてもエラーとなってしまいます。
筆者は「関数名(変数1,変数2)」のように関数名を呼び出した()内に記入した変数を入力として渡し、出力は「出力を受け取りたい変数名=関数名(変数1,変数2)」と関数の呼び出し元で用意した変数で受け取るというプログラムに思考が染まっていました。
そのため出力を受け取る変数も当然のように呼び出し元のワークフローで初期化処理を行っていたため、呼び出し先ワークフローの代入処理でオブジェクト参照エラーが発生することの原因が分からず理解するまでに時間がかかってしまいました。

補足:ここで解説したのは「出力」のみでコーディングしたい場合に気を付けるポイントです。方向を「入力/出力」に設定していれば呼び出し元ワークフローで初期化した配列等の変数を引数で渡しても呼び出し先ワークフロー先で問題なく使えます。引数受け渡しの入出力をきっちり管理したい人は後述するように呼び出し先ワークフロー内で初期化を行うことで「出力」のみでの処理を作成することが可能となります。

以下に初期化処理を行う場所が間違っているためにオブジェクト参照エラーになってしまう例を示します。

図7:出力引数未初期化による受け渡し
拡大
図7:出力引数未初期化による受け渡し

正しく動作させるには呼び出し元の初期化処理を削除し、呼び出し先で以下の処理に修正するとout_aの値をaに返すので正常に動くようになります。

図8:呼び出し先の出力引数の配列初期化&代入処理
拡大
図8:呼び出し先の出力引数の配列初期化&代入処理

3種類の方向を使った引数設定例の解説

前章までは引数設定の方法や概要、筆者のハマりポイントを解説してきました。
本章では、引数を理解するための簡単なワークフローを作成し、解説していきます。

【プログラム概要】
入力、出力、入出力、3つの方向を指定した引数を設定し、動作を確認するための
ReceiveArgument.xamlというワークフローファイルを作成します。
これをmainワークフローから「ワークフローファイルを呼び出し」アクティビティを使って呼び出し、動作を確認します。

以下にこのプログラムの流れを説明します。
①mainワークフローの変数として以下を用意します。

図9:mainワークフローで使用する変数一覧
拡大
図9:mainワークフローで使用する変数一覧

②ReceiveArgument.xamlワークフローの引数パネルで以下のように設定を行います。
※「名前」は「値」との混同を避けるため入力/出力は「io_」、入力は「in_」、出力は「out_」を先頭に付与しています。

図10:ReceiveArgumentワークフローの引数パネル
拡大
図10:ReceiveArgumentワークフローの引数パネル

③Mainワークフローにて「ワークフローを呼び出し」アクティビティを用意し引数をインポートして以下のように値を設定します。

図11:「ワークフローを呼び出し」の引数をインポートの設定
拡大
図11:「ワークフローを呼び出し」の引数をインポートの設定

④ReceiveArgumentワークフローにて以下の処理を実装します。
⑴out_sumを初期化する。
⑵out_sumにio_value1+in_value2の値を代入する。
⑶io_value1に0を代入する。
⑷in_value2に0を代入する。

⑤mainワークフローにて各変数の値を「メッセージボックス」アクティビティを使用して表示します。

⑥呼び出したワークフローReceiveArgument.xamlの処理後のmainワークフロー内の値がどのように変化したかメッセージボックスに表示された値をみて確認します。

以下に各ワークフローの図を示します。
【mainワークフロー(呼び出し元)】

図12:mainワークフロー
拡大
図12:mainワークフロー

【ReceiveArgumentワークフロー(呼び出し先)】

図13:ReceiveArgumentワークフロー
拡大
図13:ReceiveArgumentワークフロー

以下にこのプログラムを実行した結果を示します。

図14:処理後のvalue1の値
拡大
図14:処理後のvalue1の値
図15:処理後のvalue2の値
拡大
図15:処理後のvalue2の値
図16:処理後のsumの値
拡大
図16:処理後のsumの値

各変数の変化を以下の表に示します。

表2:処理前後の変数値の変化まとめ
拡大
表2:処理前後の変数値の変化まとめ

上記の表からReceiveArgument.xamlワークフローの処理内容がmainワークフローの変数に影響を与えているのは方向に「出力」が含まれているもののみとなっていることが分かります。

では出力結果を変数ごとに詳細に分析していきましょう。
【value1】
まずはvalue1から見てみましょう。
value1はmainワークフローで1を設定された後、引数の方向を「入力/出力」として渡されています。
方向に入力が含まれているのでio_value1にはvalue1の値がそのまま渡され、「ReceiveArgument.xaml」内の処理で1がそのままout_sumに加算されます。
その後、io_value1には0が代入されます。引数設定には出力も設定されているのでmainワークフローのvalue1は戻り値としてin_value1の値0を受け取ります。その結果、メッセージボックスには0が出力されました。

【value2】
次にvalue2です。
value2はmainワークフローで2を設定された後、引数の方向を「入力」として渡されています。
方向に入力が含まれているのでin_value2にはvalue2の値がそのまま渡され、「ReceiveArgument.xaml」内の処理で2がそのままout_sumに加算されます。
その後、in_value2には0が代入されます。ここでvalue1と違うのは出力の設定がされていないためmainワークフローのvalue2は戻り値としてin_value2の値0を受け取りません。その結果、メッセージボックスに表示される値はmainワークフローで設定した2のままとなりました。

【sum】
最後にsumです。
sumはmainワークフローで0を設定された後、引数の方向を出力として渡されています。
方向は出力のみなのでout_sumにsumの値は渡されません。そのためout_sumはReceiveArgument.xamlワークフロー内で初期化をする必要があります。
※補足:今回の例で使用しているInt32型は配列型等の初期化が必要な型ではないため初期化をしなくてもプログラムは正常に動きます。
その後、out_sumにはio_value1の値1、in_value2の値2が加算された値の3が代入されます。
ReceiveArgument.xamlワークフローの処理が終わるとout_sumの値が戻り値としてsumに返ってくるためメッセージボックスには3が出力されます。

まとめ

いかがだったでしょうか?
少し長めな解説になってしまいましたが、このブログを読んでUiPathでワークフローを呼び出す際の引数の扱い方を理解していただけたら幸いです。

余談:筆者も引数のインポート機能の使い方をきちんと理解していればそこまでつまずくポイントではなかったと当時を振り返っています。後日読んだ初級~中級者向けの技術書に詳しい引数の扱い方が記載されていました。どうしても分からないという方はそういった技術書を読んでみるのも手っ取り早いかもしれません。(ネットで探しても引数の設定方法が詳しく書かれたサイトは2021年3月現在であまりなかったので、、、)