UiPathのカスタム入力アクティビティでデータの入出力

前回のUiPathの入力ダイアログで初期値をいれたり複数選択するようにする方法 | while(isプログラマ)の続き(余談ですが、WordPress5.0.1にアップデートしたらエディタがかなり変更になったので、Classic Editorというプラグインをインストールして元の形式に戻しました)。

前回、入力ダイアログアクティビティについて説明しましたが、このアクティビティは簡単には使えるものの、制約も多く、汎用的に使いたいと思ってもできないことがあります。

そこで使ってほしいのが、『カスタム入力アクティビティ』。どういうものかというと、HTML形式のフォームを作って、それを入力ダイアログ代わりに使うというものです(参考:2018.3リリース新機能のご案内 – 日本 / お知らせ – UiPath Community ForumUiPath Developer Community 第7回ワークショップ 覚え書き「カスタム入力アクティビティ」 – Qiita)。v2018.3と結構最近に実装された機能のため、ググってもこのアクティビティについて書かれてあるサイトがあまりないため、この機能を知ったときは結構衝撃的でした。

とりあえず、今回は前回までに入力ダイアログで実装した部分をすべてこのHTMLに置き換えていきたいと思います。まずはフォームとなるHTMLを作成していきます。下記のようなHTMLをロボットファイルのプロジェクトフォルダに「form」というフォルダを作成し、その中に「form.html」という名前で作成することにします。

<!DOCTYPE html>
<html lang="jp">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        span.item_name{
            display:inline-block;
            width:70px;
            font-weight:bold;
            text-align:right;
        }
        #ok_btn{
            width:100px;
            height:50px;
            margin-left: 70px;
        }
    </style>
</head>
<body>
    <span class="item_name"><label for="url">URL:</label></span>
    <input type="text" value="am-yu.net" id="url">
    <br>
    <span class="item_name">並び順:</span>
    <label>
        <input type="radio" name="sort" value="count">人気
    </label>
    <label>
        <input type="radio" name="sort" value="new">新着
    </label>
    <label>
        <input type="radio" name="sort" value="eid" checked>すべて
    </label>
    <br>
    <span class="item_name"><label for="pageNum">取得数:</label></span>
    <input type="number" id="pageNum" value="100">
    <br>
    <input type="button" id="ok_btn" value="OK">
    <script>
        var url = document.getElementById('url');
        var sorts = document.getElementsByName('sort');
        var pageNum = document.getElementById('pageNum');
        // 並び順の選択値を取得
        function getCheckedValue(objs){
            for(var i = 0, len = objs.length; i < len; i ++){
                if(objs[i].checked){
                    return objs[i].value;
                }
            }
            return '';
        }
        // OKボタンクリック時の処理
        document.getElementById('ok_btn').addEventListener('click', function(e){
            var sortVal = getCheckedValue(sorts);
            window.external.setResult(url.value + ',' + sortVal + ',' + (pageNum.value - 0));
        });
    </script>
</body>
</html>

ここで一つ気を付けたほしいのが、5行目にあるように「」という記述をいれること(公式のサンプルでは「」ですが)。このカスタム入力アクティビティのレンダリングはIEを利用しているのですが、この記述がないとどうやらIE7モードで動いてしまうようです。

そして、このソースの一番の肝は56行目の「window.external.setResult(url.value + ',' + sortVal + ',' + (pageNum.value - 0));」の部分。このsetResultという関数を使うことで、UiPath側に文字列として値を渡すことができます。公式ではJSONで記述しているみたいなんですが、今回は簡単にCSVで記述して返すことにします。

また、今回のHTMLでは並び順のデフォルトに「すべて」を指定し、取得数は数値入力としてデフォルトを100としました。こういうことは入力ダイアログではできないことですね。

つづいて、UiPath側は前回ダイアログを使っていた箇所をすべて削除し、カスタム入力に置き換えます。今回の場合だと、URLに"form/form.html"、結果にretValという文字列変数を指定します。このretValはCSV形式なので、retValArrというString型の配列にSplit関数を使って渡し、前回urlやsortPropやpageNumとしていたところをretValArrの値に置き換えます。

実行すると下記のような画面が表示されます。

無駄にサイズが大きいですね。JavaScriptのresizeToメソッドでサイズを変更できるかと思いきや、できませんでした。ググってみるとフォーラムでどうやったらサイズを変更できるのか質問している人がいて、運営っぽい人が「バグっぽいので調べて対応します」と書いてあると思われるページを見つけました(New Custom Input activity - RPA Dev Advanced / Bug Reports - UiPath Community Forum)。早く、指定のサイズで開くようにできるようになってほしいです。

話は戻って、先ほどのOKボタンを押すと、うまく動きます。ただし、右上の×ボタンで閉じるとretValには空文字""が入るため、途中でエラーとなって落ちます。どうしようかなと思ったのですが、自分が関わった業務では、retValが空文字の場合、下記のように繰り返し(後判定)アクティビティを使って、retValが空文字の場合は再度開くようにしました(もちろん、場合によっては×ボタンを押せば即プログラムを終了するようにしたり、何もしないでエラーを発生させるというほうがいいこともあると思います)。

つづいて、カスタム入力に値を渡してみたいと思います。ウェブページなので、GETパラメータにしたらいいかな? と思ったのですが、URIに「?」が含まれているとエラーが発生しました。

仕方がないので、ハッシュ(アンカー)を利用することに。URIの後に#を書いて、その後にCSV形式で値をセットします。

HTMLファイルは下記のように変更。

<!DOCTYPE html>
<html lang="jp">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        span.item_name{
            display:inline-block;
            width:70px;
            font-weight:bold;
            text-align:right;
        }
        #ok_btn{
            width:100px;
            height:50px;
            margin-left: 70px;
        }
    </style>
</head>
<body>
    <span class="item_name"><label for="url">URL:</label></span>
    <input type="text" value="" id="url">
    <br>
    <span class="item_name">並び順:</span>
    <label>
        <input type="radio" name="sort" value="count">人気
    </label>
    <label>
        <input type="radio" name="sort" value="new">新着
    </label>
    <label>
        <input type="radio" name="sort" value="eid">すべて
    </label>
    <br>
    <span class="item_name"><label for="pageNum">取得数:</label></span>
    <input type="number" id="pageNum">
    <br>
    <input type="button" id="ok_btn" value="OK">
    <script>
        var url = document.getElementById('url');
        var sorts = document.getElementsByName('sort');
        var pageNum = document.getElementById('pageNum');
        window.addEventListener('load', function(){
            // ハッシュ値を取得してカンマでスプリット
            var csvs = location.hash.slice(1).split(',');
            // URL
            url.value = csvs[0];
            // 並び順
            for(var i = 0, len = sorts.length; i < len; i++){
                if(sorts[i].value === csvs[1]){
                    sorts[i].checked = true;
                    break;
                }
            }
            // 取得数
            pageNum.value = csvs[2];
        });
        // 並び順の選択値を取得
        function getCheckedValue(objs){
            for(var i = 0, len = objs.length; i < len; i ++){
                if(objs[i].checked){
                    return objs[i].value;
                }
            }
            return '';
        }
        // OKボタンクリック時の処理
        document.getElementById('ok_btn').addEventListener('click', function(e){
            var sortVal = getCheckedValue(sorts);
            window.external.setResult(url.value + ',' + sortVal + ',' + (pageNum.value - 0));
        });
    </script>
</body>
</html>

フォームのデフォルト指定をなくし、JavaScriptのロード時のイベントでハッシュを取得してそれぞれをデフォルト値としてセットしています。

動かすと確かに、渡した値がセットされました。

値を渡す方法としては微妙かもしれないですが、多分一番簡単な値の渡し方だと思います。渡すデータ量が多くなるようだと、一時ファイルを作ってそこから呼び出すようにしたほうがいいかもしれないです。

これができるなら、UiPathで(HTMLを使った)GUIアプリケーションなんてものも作れそうですね。

コメント

タイトルとURLをコピーしました