<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>ミツエーリンクス RPA Blog</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/" />
    <link rel="self" type="application/atom+xml" href="https://www.mitsue.co.jp/knowledge/blog/rpa/atom.xml" />
    <id>tag:www.mitsue.co.jp,2018-07-30:/knowledge/blog/rpa/19</id>
    <updated>2022-06-20T06:32:59Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type</generator>

<entry>
    <title>テキストの類似度を使ってモジュールを判定してみよう</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/202206/20_1158.html" />
    <id>tag:www.mitsue.co.jp,2022:/knowledge/blog/rpa//19.1885</id>

    <published>2022-06-20T02:58:58Z</published>
    <updated>2022-06-20T06:32:59Z</updated>

    <summary> Webサイトのリニューアルのとき、リニューアル前のページからリニューアル後のペ...</summary>
    <author>
        <name>RPAエンジニア 小林</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.mitsue.co.jp/knowledge/blog/rpa/">
        <![CDATA[<div class="c-media -fullWidth">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220620_01.jpg" width="961" height="540" alt=""></div>
</div>

<p>Webサイトのリニューアルのとき、リニューアル前のページからリニューアル後のページにデータを移行することがあります。そのとき、リニューアル前のページで使われていたある1つのモジュールが何のモジュールか判断したいとします。人間の場合、ブラウザで表示されるWebページを見たり、ソースの内容からどのモジュールが使われているかを判断しますが、今回はUiPathのRPAロボットによって実験的にモジュールを判定する方法をご紹介します。</p>
<h2>「StringSimilarity.NET」パッケージをプロジェクトにインストールする</h2>
<p>UiPath Studioの画面の「パッケージを管理」リボンをクリックします。するとウィンドウが表示されるので、ウィンドウ左の「すべてのパッケージ」を選択して、検索ボックスに「StringSimilarity.NET」と入力します。パッケージ一覧の中にいくつか候補が表示されますが、パッケージ名が「StringSimilarity.NET」でバージョンが5.0.0（執筆時点の最新バージョンです）のものを選択します。ウィンドウ右上の「インストール」ボタンをクリックした後に右下の「保存」ボタンをクリックしてプロジェクトにパッケージをインストールします。</p>
<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220620_02.png" width="735" height="460" alt=""></div>
<p class="c-media__caption -small">「パッケージを管理」ウィンドウ画面</p></div>]]>
        <![CDATA[<h2>モジュールのテンプレートHTMLテキストファイルを用意する</h2>
<p>リニューアル前のページで使われているモジュールのソースを記入したテンプレートHTMLテキストファイルを、モジュール1種類に対して1つずつ作成します。このとき、モジュール内のテキストや属性の値は空にします。ファイル名はそのモジュールだとわかるように命名します。作成したファイルは1つのフォルダーにまとめて保存しておきます。</p>
<h2>モジュールごとにテキストや属性の値を空にする</h2>
<p>リニューアル前のページからモジュールのHTMLを取得して、そのモジュールのテキストや属性の値を空にします。ここで、ページ全体のHTMLテキストの中からモジュールのHTMLテキストを取得したり、モジュール内のテキストや属性の値を空にする操作は、「AngleSharp」というパッケージをプロジェクトにインストールすることで実現できます。詳しい使い方についてはまた改めて別の記事でご紹介する予定です。</p>
<h2>「StringSimilarity.NET」の使い方</h2>
<p>まず、変数パネルで変数を追加します。型名を「F23.StringSimilarity.NormalizedLevenshtein」、既定値を「New F23.StringSimilarity.NormalizedLevenshtein()」として初期化します。次に、<a href="https://docs.uipath.com/activities/lang-ja/docs/assign">代入（System.Activities.Statements.Assign）アクティビティ</a>で右辺に「変数名.Similarity(比較したい文字列1, 比較したい文字列2)」と入力して、左辺にDouble型の変数を入力します。すると、左辺の変数に0から1の間の数値で2つの文字列の類似度が格納されます。</p>
<h2>HTMLテキストの類似度を取得してモジュールを判定する</h2>
<p>代入アクティビティで、右辺を「Directory.GetFiles(テンプレートHTMLテキストファイルを保存したフォルダーのパス)」とし、左辺に配列型の変数を入力して、テンプレートHTMLテキストファイルのパスの配列を取得します。<a href="https://docs.uipath.com/activities/lang-ja/docs/for-each">繰り返し（コレクションの各要素）（UiPath.Core.Activities.ForEach）アクティビティ</a>でこの配列を指定します。</p>
<h3>繰り返し内での操作</h3>
<p><a href="https://docs.uipath.com/activities/lang-ja/docs/read-text-file">テキストファイルを読み込み（UiPath.Core.Activities.ReadTextFile）アクティビティ</a>で、配列の要素であるテンプレートHTMLテキストファイルのパスを指定してそのファイルを読み込みます。代入アクティビティを使って右辺を「変数名.Similarity(テキストや属性値を空にしたモジュールのHTMLテキストの変数, 読み込んだテンプレートHTMLテキストの変数)」とし、左辺をDouble型の変数とします。<a href="https://docs.uipath.com/activities/lang-ja/docs/else-if">条件分岐（UiPath.Core.Activities.IfElseIf）アクティビティ</a>を使い、その数値がそれまでの繰り返しの最大値よりも大きかった場合、新しくその数値を最大値とし、読み込んだテンプレートHTMLテキストのファイル名を代入アクティビティを使って一時的に変数に格納します。そうすることで、繰り返し処理が終わったときに最も類似度の高かったモジュールが何かを、変数に格納されたファイル名から判定できます。</p>
<p>モジュールによっては、例えば画像の要素がaタグで囲われていたりいなかったりというHTMLテキストの揺らぎがあるので、完全にテンプレートHTMLテキストに一致していなくても、RPAロボットでどのモジュールの可能性が一番高いかを判定できます。ただ、HTMLの記述が似ているほかのモジュールと誤って判定する可能性もあるので、このやり方は補助的に使用するのが良いと思います。RPAロボットでのモジュールの判定は、最初にモジュールのタグ名やクラス名が一致するかどうかで判定して、それらが同じでHTMLの記述が異なる別々のモジュールがある場合などに今回の方法を使用するとよいのではないでしょうか。</p>]]>
    </content>
</entry>

<entry>
    <title>【UiPath モダンデザイン】開発がさらに捗る！今日から使えるオブジェクトリポジトリ</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/202205/23_1140.html" />
    <id>tag:www.mitsue.co.jp,2022:/knowledge/blog/rpa//19.1857</id>

    <published>2022-05-23T02:40:50Z</published>
    <updated>2022-05-23T02:41:09Z</updated>

    <summary> UiPath Studio 2021.10からモダンデザインが導入され、UIオ...</summary>
    <author>
        <name>RPAエンジニア 小林</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.mitsue.co.jp/knowledge/blog/rpa/">
        <![CDATA[<div class="c-media -fullWidth">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220520_01.jpg" width="961" height="540" alt=""></div>
</div>

<p><br />
<p>UiPath Studio 2021.10からモダンデザインが導入され、UIオブジェクトを一元管理するオブジェクトリポジトリが使えるようになりました。従来のUiPathにはなかった機能なので難しく感じる人もいるかもしれませんが、実はとても便利な機能です。今回は、オブジェクトリポジトリの使い方や導入の際の考え方を紹介します。</p></p>

<p>オブジェクトリポジトリは、簡単に言ってしまえばUI要素を1カ所でまとめて管理するための機能です。ロボットを開発する中で、何度も出てくる値や変更するかもしれない値は変数や引数として扱います。それと同様に、UI要素もまとめて管理してしまおうというのがオブジェクトリポジトリの考え方です。</p>

<h2>オブジェクトリポジトリの使い方</h2>

<p>※オブジェクトリポジトリを使うにはUiPath Studioの「モダンデザインエクスペリエンス」が有効化されている必要があります。詳しくは<a href="/knowledge/blog/rpa/202204/12_1442.html">こちら</a>の記事をご覧ください。</p>

<h3>オブジェクトリポジトリにUIオブジェクトを登録する</h3>

<p>UiPathのオブジェクトリポジトリではオブジェクトは「どのアプリ」の「どの画面」の「どの要素」かを指定して登録します。今回は例として、<a href="/knowledge/blog/">Blogトップページ</a>にあるRPA BlogへのリンクのUI要素を取得してみようと思います。まず、UiPath Studioでオブジェクトリポジトリの「プロジェクトUI記述子」を右クリックして新しいアプリケーションを作成します。今回はChromeを使うのでアプリケーション名は「Chrome」とします。</p>

<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220520_02.png" width="498" height="441" alt=""></div>
<p class="c-media__caption -small">オブジェクトリポジトリにアプリケーションを作成する</p></div>]]>
        <![CDATA[<p>次は今作成したアプリケーションに画面を追加します。先ほど作成したアプリケーション（Chrome）を右クリックして画面を作成します。画面名（今回は「Blog_ミツエーリンクス」とします）を入力し、操作したいアプリケーション上の画面を指定して作成できます。</p>

<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220520_03.png" width="565" height="546" alt=""></div>
<p class="c-media__caption -small">オブジェクトリポジトリに画面を作成する</p></div>

<p>画面を作成できたら、同じ要領で作成した画面「Blog_ミツエーリンクス」を右クリックして要素を作成します。要素名（今回は「RPA Blog」とします）を入力し、要素を指定して作成します。</p>

<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220520_04.png" width="601" height="682" alt=""></div>
<p class="c-media__caption -small">オブジェクトリポジトリに要素を作成する</p></div>

<p>これでオブジェクトリポジトリへのUIオブジェクトの追加が完了しました。最終的には次の図のように、アプリケーション「Chrome」の配下に「Blog_ミツエーリンクス」の画面があり、さらにその配下に「RPA Blog」の要素があるという構成になっていると思います。</p>

<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220520_05.png" width="459" height="373" alt=""></div>
<p class="c-media__caption -small">オブジェクトリポジトリに登録したUIオブジェクトの構成</p></div>

<h3>UIオブジェクトとアクティビティを関連付ける</h3>

<p>続いてオブジェクトリポジトリに登録したUIオブジェクトを各アクティビティに反映させます。今回は「RPA Blog」のリンクをクリックするフローを考えます。まず、Chromeを使うために<a href="https://docs.uipath.com/activities/lang-ja/docs/n-application-card">アプリケーション/ブラウザーを使用（UiPath.UIAutomationNext.Activities.NApplicationCard）アクティビティ</a>を使います。アプリケーション/ブラウザーを使用アクティビティを開いたらオブジェクトリポジトリの画面「Blog_ミツエーリンクス」を同アクティビティにドラッグアンドドロップするだけです。クリックに関しても同様に、アプリケーション/ブラウザーを使用アクティビティの中に配置した<a href="https://docs.uipath.com/activities/lang-ja/docs/n-click">クリック（UiPath.UIAutomationNext.Activities.NClick）アクティビティ</a>に要素「RPA Blog」をドラッグアンドドロップします。これでRPA Blogのリンクをクリックするフローのできあがりです。</p>

<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220520_06.png" width="944" height="540" alt=""></div>
<p class="c-media__caption -small">UIオブジェクトをアクティビティにドラッグアンドドロップする</p></div>

<p><br />
<h2>オブジェクトリポジトリを使うメリット</h2></p>

<p>ここまでオブジェクトリポジトリにUIオブジェクトを登録してフロー内で利用する方法を紹介しました。UI要素を管理する場所が個々のアクティビティからオブジェクトリポジトリに変わっただけのように見えますが、これには大きなメリットがあります。</p>

<p>まず、UI要素の再利用が容易になるという点です。オブジェクトリポジトリに登録した要素は、オブジェクトリポジトリに対応したアクティビティにドラッグアンドドロップするだけで使えます。同じ要素を何度も操作するロボットの場合、何度も画面上で指定せずに済みます。また、オブジェクトリポジトリはUIライブラリプロジェクトとして切り出しパブリッシュすることで共有することもできるので、チーム開発もしやすくなります。</p>

<div class="c-media">
    <div class="c-media__image">
    <img src="/knowledge/blog/rpa/img/20220520_07.png" width="459" height="373" alt=""></div>
    <p class="c-media__caption -small">オブジェクトリポジトリからUIライブラリを作成する</p></div>

<p>もう1つのメリットは、UI要素の修正が容易になるという点です。操作対象のUI要素のセレクタに変更があった際も、オブジェクトリポジトリのUIオブジェクトを右クリックして表示される「記述子を編集」から修正するだけです。オブジェクトの修正はそのオブジェクトを参照するアクティビティにも適用されるので、対象のオブジェクトを使ったアクティビティがいくつあろうと、1個のオブジェクトを修正するだけで対応できます。</p>

<p>このように、オブジェクトリポジトリを使うメリットは大きいといえます。一方で、すべてのUI要素をオブジェクトリポジトリに登録して管理するのは面倒という場合もあると思います。それではどの様な場面でオブジェクトリポジトリを使うとより効果的なのでしょうか？後々の管理のしやすさを考えると基本的にUI要素は一通りオブジェクトリポジトリで管理できるのが理想ですが、まずは複数のアクティビティで共通のセレクタを使っていたり、今後変更する可能性があるUI要素を使っていたりする部分だけでもオブジェクトリポジトリで管理すると開発の効率が上がると思います。特に複数人でロボットを共同開発する際には、あらかじめオブジェクトリポジトリで管理するUI要素に目星をつけておいたり、特定のアプリの操作に関わるUI要素は必ずオブジェクトリポジトリで管理するように決めておくなど、チームルールを設けておくと良いでしょう。</p>

<p>また、オブジェクトが増えてくると、ただ雑多に並べているだけではどのオブジェクトがどのUI要素を指しているのか分かりにくくなってしまいます。そうならないために、オブジェクトの階層構造や名前を工夫して分かりやすく並べると良いでしょう。オブジェクトは基本的にアプリケーション、画面、要素の3階層に並んでいますが、要素の配下にさらに要素を追加することも可能です。または既存の要素をドラッグアンドドロップして特定の要素配下に並べることもできます。例えば下記画像のように、階層構造を工夫すれば、同じ「1つ目の記事」というUIオブジェクトでもどの要素を指しているかすぐに判断できます。チーム開発の場合変数やワークフローファイルの命名規則を決めていると思いますが、それと同様に、オブジェクトリポジトリの階層や命名についてチームルールを決めておくと良いでしょう。</p>

<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220520_08.png" width="483" height="650" alt=""></div>
<p class="c-media__caption -small">UIオブジェクトの構成を工夫する</p></div>

<p>今回はUiPathの新機能オブジェクトリポジトリをどう使うかについて考えました。オブジェクトリポジトリはハードルが高いと感じていた方にも使ってみたいと思っていただけたら幸いです。積極的に導入して、ロボット開発の効率をさらに上げていきたいですね。</p>]]>
    </content>
</entry>

<entry>
    <title>UiPathのモダンアクティビティが便利～クリックアクティビティ編～</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/202204/12_1442.html" />
    <id>tag:www.mitsue.co.jp,2022:/knowledge/blog/rpa//19.1766</id>

    <published>2022-04-12T05:42:57Z</published>
    <updated>2022-04-13T02:28:39Z</updated>

    <summary> UiPath Studio 20.10からモダンデザインが導入されました。モダ...</summary>
    <author>
        <name>RPAエンジニア 小林</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.mitsue.co.jp/knowledge/blog/rpa/">
        <![CDATA[<div class="c-media -fullWidth">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220408_01.jpg" width="961" height="540" alt=""></div></div>

<p>UiPath Studio 20.10からモダンデザインが導入されました。モダンデザインでは多くのアクティビティがより高機能なモダンアクティビティとして刷新されています。アクティビティのほかにも、レコーダー、データスクレイピングなどが新しくなっており従来とは違う新たな機能が使えるようになっています。</p>

<p>慣れるまで時間はかかりましたが、使用してみるととても便利でしたので、その内容を何回かに分けて紹介していこうと思います。</p>

<p>本日は<a href="https://docs.uipath.com/activities/lang-ja/docs/n-click">クリック(UiPath.UIAutomationNext.Activities.NClick)アクティビティ</a>編です。</p>

<p>＜便利だと感じた点＞</p>
<ul>
    <li>クリック後、画面遷移までの待機をクリックアクティビティのみで設定できる</li>
    <li>クリックのオフセットが簡単に設定できる</li>
</ul>

<p>それでは順番にご紹介します。</p>]]>
        <![CDATA[<h2>モダンアクティビティを使う準備</h2>

<p>※v2021.10以降のStudioでは、モダンデザインエクスペリエンスは既定ですべての新規プロジェクトで有効化されています。</p>

<h3>新たに作成されるすべてのプロジェクトに設定する方法</h3>
<p>[ホーム]  > [設定] > [デザイン]  > [新しいプロジェクトでモダンを使用] を[はい]に設定</p>
<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220408_02.png" width="735" height="489" alt=""></div>
<p class="c-media__caption -small">すべてのプロジェクトに設定</p></div>

<h3>特定のプロジェクトに設定する方法</h3>
<p>[プロジェクト] パネルの [プロジェクト設定]  > [全般]  >  [モダン デザイン エクスペリエンス] を[はい]に設定</p>
<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220408_03.png" width="735" height="489" alt=""></div>
<p class="c-media__caption -small">特定のプロジェクトに設定</p></div>

<p>モダンアクティビティを使用しつつクラシックアクティビティを使用することも可能です</p>

<h3>クラシックアクティビティを表示する方法</h3>
<p>[アクティビティ] パネルの[オプションを表示]  > [クラシックアクティビティを表示] にチェック</p>
<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220408_04.png" width="735" height="489" alt=""></div>
<p class="c-media__caption -small">クラシックアクティビティを表示</p></div>

<h2>クリック後、画面遷移までの待機をクリックアクティビティのみで設定できる</h2>

<p>ロボット開発をする上で一度は経験した事があると思うのですが、クリックのタイミングが合わずにエラーが発生するという事象が多々おきます。これを回避するために私が今までよく使っていたのが、<a href="https://docs.uipath.com/activities/lang-ja/docs/wait-ui-element-appear">要素を探す(UiPath.Core.Activities.WaitUiElementAppear)アクティビティ</a>や<a href="https://docs.uipath.com/activities/lang-ja/docs/on-ui-element-appear">要素が出現したとき(UiPath.Core.Activities.OnUiElementAppear)アクティビティ</a>です。</p>

<p>※待機アクティビティでも同じような処理を実現できますが、おすすめはできません。画面遷移時間によらず待機時間は一定なので、画面遷移後に余計な待機時間が発生したり、画面遷移前に後続処理が始まってしまいエラーになる可能性があるからです。</p>

<p>モダンデザインのクリックアクティビティでは［実行を検証］というオプションがあり、クリック後の要素の動作検証ができます。動作項目は、［出現］［消滅］［テキストの変化］［表示の変化］の4つがあり、これらを利用することでクリックアクティビティのみで画面遷移するまで待機することができます。</p>

<p>①クリックするターゲットを指定(※UI要素の識別方法もクラシックとは異なるのですが、あらためて紹介しようと思うので今回は割愛します)</p>
<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220408_05.png" width="735" height="489" alt=""></div>
<p class="c-media__caption -small">ターゲットを指定</p></div>

<p>②オプションメニューを開き[検証を追加]をクリックし検証ターゲットを指定</p>
<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220408_06.png" width="735" height="489" alt=""></div>
<p class="c-media__caption -small">検証を追加</p></div>
<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220408_07.png" width="735" height="489" alt=""></div>
<p class="c-media__caption -small">検証ターゲットを指定</p></div>

<p>③オプションメニューの［要素の次の動作を検証］の中から動作を指定</p>
<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220408_08.png" width="735" height="489" alt=""></div>
<p class="c-media__caption -small">動作を指定</p></div>

<p>この［実行を検証］はクリックアクティビティ以外にも<a href="https://docs.uipath.com/activities/lang-ja/docs/n-type-into">文字を入力(UiPath.UIAutomationNext.Activities.NTypeInto)アクティビティ</a>や<a href="https://docs.uipath.com/activities/lang-ja/docs/n-hover">ホバー(UiPath.UIAutomationNext.Activities.NHover)アクティビティ</a>にもあり、文字を入力すると表示される要素などの検証も1つのアクティビティで可能になります。</p>

<h2>クリックのオフセットが簡単に設定できる</h2>

<p>クリックアクティビティは通常UI要素が指し示す領域の中心部分をクリックしますが、クリックする位置の座標をあえてずらす（オフセットを設定する）こともできます。UI要素が検知する場所と実際にクリックしたい場所がずれている場合や、ある要素を足掛かりに別の（UI要素として認識できない）領域をクリックする場合などに有用な機能ですが、クラシックのクリックアクティビティではプロパティに座標を直接指定するため、数値を地道に調整する必要がありました。モダンデザインのクリックアクティビティでは、UI要素を指定する際に中心にある点をドラッグすることで簡単にオフセットを設定できます。</p>

<p>①基準となるターゲットをクリックすると真ん中にマークが表示されます。</p>
<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220408_09.png" width="735" height="489" alt=""></div>
<p class="c-media__caption -small">基準となるターゲットを指定</p></div>

<p>②そのマークをクリックしたい箇所までドラッグし、確定をクリックするとオフセット欄に数字が自動で入力されます。</p>
<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220408_10.png" width="735" height="489" alt=""></div>
<p class="c-media__caption -small">クリックしたい箇所までドラッグ</p></div>
<div class="c-media">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20220408_11.png" width="735" height="489" alt=""></div>
<p class="c-media__caption -small">オフセット欄に自動で設定される</p></div>

<p>こうすることで要素を取得できない箇所も簡単にクリックすることができるようになります。</p>

<p>このようにクラシックでは複数のアクティビティを使用して実装していた部分が1つのアクティビティで完結したり、設定方法が楽になったりなどクリックアクティビティ以外にも便利になった機能がたくさんあります！そしてクリックアクティビティはこれだけではなく、今回は割愛しましたが、UI要素の識別方法もとても便利になりましたので、そちらもあらためて紹介したいと思います。</p>]]>
    </content>
</entry>

<entry>
    <title>UiPathからPythonスクリプトを呼び出す</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/202103/23_1050.html" />
    <id>tag:www.mitsue.co.jp,2021:/knowledge/blog/rpa//19.1488</id>

    <published>2021-03-23T01:50:34Z</published>
    <updated>2021-03-23T06:37:21Z</updated>

    <summary> UiPathは自動化のための様々な機能を備えていますが、フローの中で複雑な計算...</summary>
    <author>
        <name>UI開発者 宇賀</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.mitsue.co.jp/knowledge/blog/rpa/">
        <![CDATA[<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20210323_01.jpg" height="405" width="773" alt=""></div>

<p>UiPathは自動化のための様々な機能を備えていますが、フローの中で複雑な計算やAPI連携などをしたいときに、「ここだけPythonで処理できると楽だな」と思う場面があります。今回は、UiPathでPythonスクリプトを扱うためのアクティビティについて紹介します。</p>

<h2>準備</h2>

<p>まず、前提としてマシンには<a href="https://www.python.org/">Python</a>がインストールされている必要があります。その上で、UiPathからPythonを実行するために<a href="https://docs.uipath.com/releasenotes/lang-ja/docs/uipath-python-activities">UiPath.Python.Activites</a>をインストールします。このパッケージはUiPath Studioのパッケージマネージャーからインストールすることができます。</p>
<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20210321_02.png" height="500" width="900" alt=""><span class="caption">UiPath.Python.Activitiesのインストール</span></div>

<p>パッケージをインストールできたら、Pythonスクリプトを用意します。今回は以下のようなコードが書かれたファイル「my_methods.py」で試してみます。ここではシンプルな例として関数1つを扱っていますが、複数の関数が記述されていてもかまいません。呼び出したい関数はUiPath側で指定することができます。例として扱うrepeat_string関数は、引数sとして受け取った文字列を引数nで指定された回数だけ繰り返した文字列を返す関数です。</p>

<pre><code class="python">def repeat_string(s, n):
    result = s * n
    return result
</code></pre>]]>
        <![CDATA[<h2>Pythonアクティビティの使い方</h2>

<p>UiPath.Python.Activitesをインストーして導入した各種Pythonアクティビティを使ってワークフローを組み立てていきます。構成としては、<a href="https://docs.uipath.com/activities/lang-ja/docs/python-scope">Pythonスコープ（UiPath.Python.Activities.PythonScope）</a>の中に、<a href="https://docs.uipath.com/activities/lang-ja/docs/load-script">Pythonスクリプトをロード(UiPath.Python.Activities.LoadScripts)</a>、<a href="https://docs.uipath.com/activities/lang-ja/docs/invoke-method">Pythonメソッドの呼び出し（UiPath.Python.Activities.InvokeMethid）</a>、<a href="https://docs.uipath.com/activities/lang-ja/docs/get-object">Pythonのオブジェクトを取得(UiPath.Python.Activities.GetObject)</a>のアクティビティを順に配置します。</p>

<p>まず、Pythonスコープのプロパティで、「パス」にPythonの実行ファイル（python.exe）が保存されているフォルダを指定します。「WorkingFolder」にはPythonを実行したいフォルダを指定します。今回は作成しているプロジェクトと同じフォルダに指定しています。「ターゲット」は扱うPythonか32bit版か64bit版かによって切り替えます。今回扱っている例では32bit版Pythonを使って実行したのでx86を指定していますが、64bit版Pythonを使う場合はx64を指定してください。</p>
<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20210321_03.png" height="600" width="900" alt=""><span class="caption">Pythonスコープ</span></div>

<p>Pythonスクリプトをロードのアクティビティでは、Pythonスクリプトを読み込んでPythonObjectとして出力します。プロパティの「ファイル」に読み込みたいPythonスクリプトファイルのパスを設定します。結果はPythonObject型の変数として出力され、この変数を使ってこの後の処理が行われます。</p>
<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20210321_04.png" height="600" width="900" alt=""><span class="caption">Pythonスクリプトをロード</span></div>

<p>Pythonメソッドの呼び出しアクティビティでは、上記Pythonスクリプトをロードで読み込ませたPythonスクリプト内の関数を呼び出すことができます。プロパティの「インスタンス」に上記で取得したPythonObject型変数を設定し、「名前」には呼び出したい関数の名前を入力します。入力パラメータには関数に渡したい引数を{}で列挙して入力します（正確にはIEnumrable型の変数）。図の例のように{"abc", 3}と設定すると、Python関数の第1引数sに文字列「abc」、第2引数nに整数「3」が渡されます。結果にはPythonObject型の変数を設定します。</p>
<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20210321_05.png" height="600" width="900" alt=""><span class="caption">Pythonメソッドの呼び出し</span></div>

<p>Pythonのオブジェクトを取得アクティビティでは、上記メソッドの呼び出しで取得したPythonObject変数を入力プロパティに設定します。TypeArgumentには、Python関数の戻り値として期待される型を指定し、出力プロパティにはその型の変数を設定します。今回例として扱っている関数はstr型（UiPathのString型に相当）を返すので設定する型はStringです。</p>
<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20210321_06.png" height="600" width="900" alt=""><span class="caption">Pythonメソッドのオブジェクトを取得</span></div>

<p>これですべて設定はできたので、実際にStr_Resultの値を出力してみると「abc」を3繰り返した文字列「abcabcabc」が出力されており、Pythonスクリプトの関数が実行されたことが分かります。</p>
<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20210321_07.png" height="548" width="670" alt=""><span class="caption">実行結果</span></div>


<h2>エラーの扱い</h2>

<p>最後に、エラーが起きた場合の処理について考えてみます。上記例ではPythonスクリプトが正しく実行されることが確認されましたが、状況によってはエラーが生じることもあります。例えば上記Pythonメソッドの呼び出しアクティビティからrepeat_string関数を呼び出し、繰り返し回数（第2引数）に整数でない値を入れて実行してみると、エラーが生じて処理が止まってしまいます。</p>

<p>Python側で起きたエラーをUiPathのエラー画面だけから読み解こうとすると複雑なので、Pythonのエラー内容をUiPathに渡せるようにしておいたほうが問題を切り分けやすくなります。例えば次のコードのようにtracebackモジュールを用いて、結果と一緒にトレースバックを返すようにしておけば、UiPath側でPythonのトレースバックの内容を変数として受け取れます。</p>

<pre><code class="python">import traceback

def repeat_string(s, n):
    result = ""
    error = ""
    try:
        result = s * n
    except Exception:
        error = traceback.format_exc()
    return result, error
</code></pre>

<p>この例のように実装した場合、関数の戻り値は2つになります。戻り値が複数ある関数の場合、UiPath側では配列変数で受け取ることができます。今回の例では戻り値は2つとも文字列なので、String型の配列で実行結果を受け取ります。戻り値に異なる型が混在する場合はObject型の配列で受け取ることができます。</p>
<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20210321_08.png" height="600" width="900" alt=""><span class="caption">戻り値としてString型の配列を設定する例</span></div>

<p>あとは、トレースバックの内容によって例外をスローしたり、ログとして出力した上で処理を継続したりするなど、目的に応じた例外処理をすると良いでしょう。</p>

<p>今回は、UiPathからPythonスクリプトを呼び出す方法を紹介しました。UiPathとPythonはそれぞれ得意とする領域が異なります。例えばUI操作の自動化であればUiPathのほうが簡単に実現できますし、複雑な計算をしたい場合はPythonでスクリプトを書いてしまったほうが扱いやすいでしょう。また、作りたい処理に関連するツールを探す際、UiPathパッケージにはないがPythonライブラリにはある（またはその逆）という場合もあります。そのような両者を連携することで今まで一方だけでは難しいと思っていた自動化を実現できるかもしれません。UiPathとPythonの長所をうまく組み合わせて、自動化の幅を広げていきたいですね。</p>]]>
    </content>
</entry>

<entry>
    <title>メールトリガーでUiPath Orchestratorのジョブを実行する方法</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/202102/01_1013.html" />
    <id>tag:www.mitsue.co.jp,2021:/knowledge/blog/rpa//19.1446</id>

    <published>2021-02-01T01:13:55Z</published>
    <updated>2021-02-01T01:14:16Z</updated>

    <summary> 普段の業務の中で、ある条件に当てはまるメールを受信したときにUiPath Or...</summary>
    <author>
        <name>UI開発者 宇賀</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.mitsue.co.jp/knowledge/blog/rpa/">
        <![CDATA[<div class="c-media -fullWidth">
<div class="c-media__image">
<img src="https://www.mitsue.co.jp/knowledge/blog/rpa/img/20210129_01.jpg" width="961" height="540">
</div>
</div>

<p>普段の業務の中で、ある条件に当てはまるメールを受信したときにUiPath Orchestratorにある特定のプロセスのジョブを実行したい場合があると思います。今回はOutlook VBAを使ってメール受信をトリガーにしてジョブを実行する方法をご紹介します。</p>
<p>前提として、Microsoft Outlookでマクロを編集できるようにしておいたり、マクロに自己署名をつけておく必要があります。</p>
<p>メインのプロシージャのコードは下記のようになります。</p>
<pre><code class="vb">Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)

Const TASK_SUBJECT = "メールの件名"
Const PROCESS_NAME = "UiPath Orchestrator上のプロセス名"
Dim MailMessage
Dim Token As String, ReleaseKey As String

Set MailMessage = Session.GetItemFromID(EntryIDCollection)

If InStr(MailMessage.Subject, TASK_SUBJECT) &lt;&gt; 0 Then
    Token = UiPath_Authenticating 'アクセストークンを取得するプロシージャを実行して戻り値を格納
    ReleaseKey = UiPath_RequestReleaseKey(Token, PROCESS_NAME) 'リリースキーを取得するプロシージャを実行して戻り値を格納
    UiPath_StartJob Token, ReleaseKey 'ジョブの実行を命令するプロシージャを実行
End If

End Sub</code></pre><p>このプロシージャは、指定したメールの件名が受信したメールの件名に含まれていたときに、指定したプロセス名のジョブを実行する命令をOrchestratorに対して行います。送信元を指定したり本文に特定の文字列が含まれている場合などを条件にしたいときはIf文の条件を適宜修正してください。</p>
<p>注意点として、このプロシージャはメールを受信したときに実行されるので、Outlookを常に起動させておく必要があります。</p>
<p>また、ジョブを実行するにはいくつかの段階を踏む必要があります。</p>
<ol>
<li><p>まず、アクセストークンを取得します（上記コードのUiPath_Authenticatingプロシージャ）。</p>
</li>
<li><p>次にそのアクセストークンでプロセスのリリースキーを取得します（上記コードのUiPath_RequestReleaseKeyプロシージャ）。</p>
</li>
<li><p>最後にアクセストークンとリリースキーでプロセスのジョブを実行する命令をします（上記コードのUiPath_StartJobプロシージャ）。</p>
</li>
</ol>
<p>以下はそれぞれの段階に対応するプロシージャのコードです。</p>
<h2>アクセストークンの取得（UiPath_Authenticating）</h2>
<pre><code class="vb">Function UiPath_Authenticating() As String

Dim sURL As String, sHTML As String, Body As String, Token As String
Dim oHttp As Object
Dim Doc, JsonObject

Set oHttp = CreateObject("MSXML2.ServerXMLHTTP")
sURL = "https://account.uipath.com/oauth/token"
oHttp.Open "POST", sURL, False
oHttp.setRequestHeader "Content-type", "application/json"
oHttp.setRequestHeader "X-UIPATH-TenantName", "テナント名"
Body = "{""grant_type"" : ""refresh_token"",""client_id"" : ""クライアントID"",""refresh_token"" : ""リフレッシュトークン""}"
oHttp.Send Body

sHTML = oHttp.ResponseText
Set Doc = CreateObject("HtmlFile")
Doc.Write "&lt;script&gt;document.JsonParse=function (s) {return eval('(' + s + ')');}&lt;/script&gt;"
Set JsonObject = Doc.JsonParse(sHTML)
Token = CallByName(JsonObject, "access_token", VbGet)

UiPath_Authenticating = Token

End Function</code></pre><p>トークン取得の要求を行い、その応答をJSONオブジェクトにしてその中からアクセストークンを取得しています。</p>
<h2>リリースキーの取得（UiPath_RequestReleaseKey）</h2>
<pre><code class="vb">Function UiPath_RequestReleaseKey(ByVal Token As String, ByVal ProjectName As String) As String

Dim sURL As String, sHTML As String, Body As String, ReleaseKey As String
Dim oHttp As Object
Dim Doc, JsonObject, Value, item
Dim i As Long

Set oHttp = CreateObject("MSXML2.ServerXMLHTTP")
sURL = "リリースキー取得APIのURL"
oHttp.Open "GET", sURL, False
oHttp.setRequestHeader "Content-type", "application/json"
oHttp.setRequestHeader "X-UIPATH-TenantName", "テナント名"
oHttp.setRequestHeader "Authorization", "Bearer " & Token
oHttp.Send

sHTML = oHttp.ResponseText
Set Doc = CreateObject("HtmlFile")
Doc.Write "&lt;script&gt;document.JsonParse=function (s) {return eval('(' + s + ')');}&lt;/script&gt;"
Set JsonObject = Doc.JsonParse(sHTML)
Set Value = CallByName(JsonObject, "value", VbGet)
For i = 0 To 100 'Orchestratorにあるプロセスが101個を超える場合は値を変更
    If CallByName(CallByName(Value, i, VbGet), "Name", VbGet) = ProjectName Then
        ReleaseKey = CallByName(CallByName(Value, i, VbGet), "Key", VbGet)
        Exit For
    End If
Next

UiPath_RequestReleaseKey = ReleaseKey

End Function</code></pre><p>リクエストキー取得の要求を行い、その応答をJSONオブジェクトにします。For文でその中から指定したプロジェクト名のリリースキーを取得します。</p>
<h2>ジョブの実行を命令（UiPath_StartJob）</h2>
<pre><code class="vb">Sub UiPath_StartJob(ByVal Token As String, ByVal ReleaseKey As String)

Dim sURL As String, sHTML As String, Body As String
Dim oHttp As Object

Set oHttp = CreateObject("MSXML2.ServerXMLHTTP")
sURL = "ジョブ実行APIのURL"
oHttp.Open "POST", sURL, False
oHttp.setRequestHeader "Content-type", "application/json"
oHttp.setRequestHeader "X-UIPATH-TenantName", "テナント名"
oHttp.setRequestHeader "Authorization", "Bearer " & Token
oHttp.setRequestHeader "X-UIPATH-FolderPath", "Orchestratorのプロセスがあるクラシックフォルダのパス"
oHttp.setRequestHeader "Content-type", "application/json"
Body = "{""startInfo"": {""RobotIds"": [],""Strategy"": ""All"",""ReleaseKey"": """ & ReleaseKey & """,""NoOfRobots"": 0}}"
oHttp.Send Body

sHTML = oHttp.ResponseText '必要に応じてログに出力する仕組みを導入する

End Sub</code></pre><p>ジョブの実行を命令する要求を行います。必要に応じて応答を出力するプロシージャなどを作成してログとして出力します。</p>
<p>メールトリガーの仕組みを業務の効率化に活用していただければ幸いです。</p>]]>
        
    </content>
</entry>

<entry>
    <title>Pythonのモジュールを使ってWordファイルからHTMLファイルを作成する方法</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/202012/12_0900.html" />
    <id>tag:www.mitsue.co.jp,2020:/knowledge/blog/rpa//19.1402</id>

    <published>2020-12-12T00:00:00Z</published>
    <updated>2020-12-12T01:32:06Z</updated>

    <summary>この記事はミツエーリンクス Advent Calendar 2020 - Adv...</summary>
    <author>
        <name>エグゼクティブ・フェロー 木達</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.mitsue.co.jp/knowledge/blog/rpa/">
        <![CDATA[<p>この記事は<a href="https://adventar.org/calendars/5763">ミツエーリンクス Advent Calendar 2020 - Adventar</a>の12日目の記事です。</p>

<p>今回は、Pythonのモジュールである<a href="https://pypi.org/project/mammoth/">mammoth</a>と<a href="https://pypi.org/project/beautifulsoup4/">beautifulsoup4</a>を使ってWordファイルからHTMLファイルを作成する方法をご紹介します。</p>

<p>この方法を採用する理由として、mammothを使ってあらかじめ指定したHTML形式でWordファイル内の文章をマークアップできることが挙げられます。それによって、既に構築されているWebサイトのコラム記事などを追加する際に、Wordファイルで原稿を書いてそのHTMLファイルを作成するというやり方が実現でき、さらにHTMLファイル作成までの時間を短縮することができます。</p>

<p>環境は、Windows 10にMicrosoft WordとPython 3.9がインストールされていて、pip（Python向けのパッケージ管理システム）からmammothモジュール、beautifulsoup4モジュールがインストールされているものとします。</p>

<p>また、html要素のパーツ（モジュール）の個別処理にはUiPathを使用します。UiPathはRPA（ロボティック・プロセス・オートメーション）の製品の1つで、「要素をクリックする」「文字を入力する」などのさまざまなアクティビティを組み合わせてワークフローを作り、処理を自動化することができます。UiPathを使うことにより、mammothでは対応しきれないモジュールごとの構成に対応させることができます。例えば、mammothでは出力するhtml要素に指定できるclassは1つのみですが、UiPathを使うことで複数のclassを加えることができます。また、後述するPythonを使った処理もUiPathのアクティビティを使用することで自動化できます。</p>

<p>全体の流れは、</p>

<ol start='1'>
<li>Wordファイルのスタイルを設定する</li>
<li>mammothのカスタムスタイルマップ機能を使用するためのテキストファイルを作成する</li>
<li>mammothでHTMLファイルを出力する</li>
<li>beautifulsoup4でhtml要素のパーツ（モジュール）に分割して出力する</li>
<li>UiPathでモジュールごとに個別処理をしてHTMLファイルを作成する</li>
</ol>

<p>となります。</p>
]]>
        <![CDATA[<h2>1. Wordファイルのスタイルを設定する</h2>

<p>mammothの機能の中にカスタムスタイルマップというものがあります。この機能を利用すると、Wordファイルで段落に指定したスタイルごとに出力されるhtml要素とクラス名を指定できます。そのためにあらかじめWordファイルで新しくスタイルを作成し、html要素ごとにそれぞれの段落にスタイルを適用します。</p>

<p>例として、Wordファイルのスタイルにmidashi1という新しいスタイルを作成します。注意点として、mammothで読み込めるWordファイルのスタイル名は英数字に限られるようです。</p>

<div class="c-media">
<div class="c-media__image">
<img src="https://www.mitsue.co.jp/knowledge/blog/rpa/img/20201212_01.png" width="735" height="489" alt=""></div>
<p class="c-media__caption -small">Wordファイルのスタイルにmidashi1を追加する</p>
</div>

<h2>2. mammothのカスタムスタイルマップ機能を使用するためのテキストファイルを作成する</h2>

<p>1.で作成したスタイルに対応するカスタムスタイルマップを記述したテキストファイルを用意します。</p>

<p>midashi1のスタイルを適用した段落を、h1要素でクラス名がtitle-01というhtml要素に出力したい場合は以下のように記述します。</p>

<pre><code>p[style-name='midashi1'] => h1.title-01:fresh</code></pre>

<p>wrapperというクラス名のdiv要素で囲って出力したい場合は以下のようにします。</p>

<pre><code>p[style-name='midashi1'] => div.wrapper > h1.title-01:fresh</code></pre>

<p>このようにWordファイルに新しく作成したスタイルごとに1行ずつカスタムスタイルマップのルールを書き、custom-style-map.txtというテキストファイルとして保存します。</p>

<h2>3. mammothでHTMLファイルを出力する</h2>

<p>下記のようにPythonでコマンドを実行し、1.でスタイルを適用したdocument.docxからcustom-style-map.txtに記述したルールに基づいて変換されたtemp.htmlを出力します。</p>

<pre><code>mammoth document.docx temp.html --style-map="custom-style-map.txt"</code></pre>

<h2>4. beautifulsoup4でhtml要素のパーツ（モジュール）に分割して出力する</h2>

<p>下記のようにPythonでコマンドを実行してtemp.htmlの中の最上位の要素（モジュール）で分割し、上から順に01.html、02.html...という名前でhtmlフォルダーに保存します。</p>

<pre><code>soup = bs4.BeautifulSoup(open("temp.html", encoding="utf-8"), "html.parser")
elements = soup.find_all(recursive=False)

i = 1
for element in elements:
    path_w = ".\\html\\" + format(str(i), "0>2") + ".html"
    s = str(element)
    with open(path_w, mode="w", encoding="utf-8") as f:
        f.write(s)</code></pre>

<h2>5. UiPathでモジュールごとに個別処理をしてHTMLファイルを作成する</h2>

<p>4.でhtmlフォルダーに作成したモジュールごとのHTMLファイルをUiPathを使って処理をします。</p>

<p>まず、<a href="https://docs.uipath.com/activities/lang-ja/docs/assign">代入（System.Activities.Statements.Assign）アクティビティ</a>でDirectory.GetFilesメソッドを使ってhtmlフォルダー内のすべてのHTMLファイルのパスを配列に格納します。</p>

<p>次に、<a href="https://docs.uipath.com/activities/lang-ja/docs/for-each">繰り返し（コレクションの各要素）（UiPath.Core.Activities.ForEach）アクティビティ</a>でファイルパスを格納した配列を指定し、そのスコープ内で<a href="https://docs.uipath.com/activities/lang-ja/docs/read-text-file">テキストをファイルから読み込み（UiPath.Core.Activities.ReadTextFile）アクティビティ</a>でHTMLファイルを1つずつ読み込みます。読み込んだHTMLテキストに対して<a href="https://docs.uipath.com/activities/lang-ja/docs/replace">置換（UiPath.Core.Activities.Replace）アクティビティ</a>などを使って出力したいモジュールの形式に修正します。修正したHTMLテキストを代入アクティビティで上から順に連結していきます。</p>

<p>最後に、各モジュールを連結したHTMLテキストを<a href="https://docs.uipath.com/activities/lang-ja/docs/write-text-file">テキストをファイルに書き込み（UiPath.Core.Activities.WriteTextFile）アクティビティ</a>で最終的な形のHTMLファイルに出力します。</p>

<div class="c-media">
<div class="c-media__image">
<img src="https://www.mitsue.co.jp/knowledge/blog/rpa/img/20201212_02.png" width="735" height="489" alt=""></div>
<p class="c-media__caption -small">UiPathの全体フローチャート</p>
</div>

<p>Wordファイルで原稿を書き、それをもとにHTMLファイルを作成したいときには今回ご紹介した方法が便利ですのでぜひ実践してみてください。</p>
]]>
    </content>
</entry>

<entry>
    <title>UiPath Orchestrator APIを使ってジョブを実行する</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/202011/24_1653.html" />
    <id>tag:www.mitsue.co.jp,2020:/knowledge/blog/rpa//19.1380</id>

    <published>2020-11-24T07:53:35Z</published>
    <updated>2020-11-24T07:52:51Z</updated>

    <summary> UiPath OrchestratorにはさまざまなAPIが用意されています。...</summary>
    <author>
        <name>UI開発者 宇賀</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.mitsue.co.jp/knowledge/blog/rpa/">
        <![CDATA[<div class="c-media -fullWidth">
<div class="c-media__image">
<img src="/knowledge/blog/rpa/img/20201124_01.jpg" width="961" height="540" alt=""></div>
</div>
<p>UiPath OrchestratorにはさまざまなAPIが用意されています。その中でも<a href="https://docs.uipath.com/orchestrator/lang-ja/v0/reference/jobs-requests#starting-a-job">Starting a Jobリクエスト</a>を使うことで、UiPath Orchestratorにパブリッシュされたプロセスのジョブを、登録したUnattendedマシンで実行することができます。</p>
<p>Cloud版Orchestratorのクラシックフォルダーにプロセスがある場合、Starting a Jobリクエストをするまでの流れは以下になります。</p>
<h2>1. APIを使用するためのAccess Tokenを取得する</h2>
<p>あらかじめOrchestrator上でAPIを使用するためのUser KeyとClient IDを取得しておきます。その上で、ヘッダーにテナント名を、本文のパラメーターにUser KeyとClient IDをそれぞれ含んだ<a href="https://docs.uipath.com/orchestrator/lang-ja/v0/reference/consuming-cloud-api#authenticating-to-your-automation-cloud-based-orchestrator-tenant">Authenticatingリクエスト</a>をPOST送信します。するとそのレスポンスのJSONからAccess Tokenを取得できます。</p>
<table>
<tbody>
<tr>
<th>ヘッダー</th>
<th>説明</th>
</tr>
<tr>
<td>X-UIPATH-TenantName</td>
<td>テナント名を指定</td>
</tr>
</tbody>
</table><table>
<tbody>
<tr>
<th>本文のパラメーター</th>
<th>説明</th>
</tr>
<tr>
<td>grant_type</td>
<td>"refresh_token"と指定</td>
</tr>
<tr>
<td>client_id</td>
<td>Client IDを指定</td>
</tr>
<tr>
<td>refresh_token</td>
<td>User Keyを指定</td>
</tr>
</tbody>
</table><h2>2. プロセス固有のRelease Keyを取得する</h2>
<p>取得したAccess Tokenとテナント名をヘッダーに、プロセス名をURLに含んだ<a href="https://docs.uipath.com/orchestrator/lang-ja/v0/reference/processes-requests#retrieving-processes-according-to-their-name">Retrieving Processes According to Their Nameリクエスト</a>をGET送信し、レスポンスのJSONからプロセスが持つ固有のRelease Keyを取得します。もしくはプロセス名を指定せずにリクエストをし、すべてのプロセスのRelease Keyを取得してその中から目的のプロセスのRelease Keyを取り出します。</p>
<table>
<tbody>
<tr>
<th>ヘッダー</th>
<th>説明</th>
</tr>
<tr>
<td>Authorization</td>
<td>"Bearer"の後に半角スペースを入れてAccess Tokenを指定</td>
</tr>
<tr>
<td>X-UIPATH-TenantName</td>
<td>テナント名を指定</td>
</tr>
</tbody>
</table><h2>3. Orchestratorにジョブの実行を要求する</h2>
<p>Access Token、Release Key、テナント名、プロセスがあるOrchestrator上のフォルダパスをヘッダーに含んだStarting a JobリクエストをPOST送信します。リクエストを送信すると登録したマシンでジョブが実行されます。</p>
<table>
<tbody>
<tr>
<th>ヘッダー</th>
<th>説明</th>
</tr>
<tr>
<td>Authorization</td>
<td>"Bearer"の後に半角スペースを入れてAccess Tokenを指定</td>
</tr>
<tr>
<td>X-UIPATH-TenantName</td>
<td>テナント名を指定</td>
</tr>
<tr>
<td>X-UIPATH-FolderPath</td>
<td>Orchestrator上のプロセスがあるフォルダを指定</td>
</tr>
</tbody>
</table><table>
<tbody>
<tr>
<th>本文のパラメーター</th>
<th>説明</th>
</tr>
<tr>
<td>startInfo</td>
<td>（例）{"ReleaseKey": "取得したRelease Key","Strategy": "All","RobotIds": [],"NoOfRobots": 0}</td>
</tr>
</tbody>
</table><p>上の例ではStrategyをAllに指定していますが、これはプロセスがクラシックフォルダーにある場合に指定ができます。</p>
<p>この一連の流れを例としてマシンのOutlookのマクロに記述することで、以下のような処理が可能になります。</p>
<ol>
<li>マシン宛てに特定のメールが届く。</li>
<li>そのメールをトリガーにしてOrchestratorにリクエストを送信する。</li>
<li>Orchestratorに登録したUnattendedマシンでジョブを実行する。</li>
</ol>
<p>このとき、メールに記載された情報を引数としてプロセスに渡すこともできます。渡し方は<a href="https://docs.uipath.com/orchestrator/lang-ja/v0/reference/jobs-requests#starting-a-job-with-custom-values-for-input-parameters">Starting a Job with Custom Values for Input Parametersリクエスト</a>のページにあるように、InputArgumentsの値の中でプロセスの引数名をキーにして渡したい情報はその値にします。</p>
<p>このように工夫次第でさまざまな自動化ができると思いますので、ぜひ試してみてください。</p>]]>
        
    </content>
</entry>

<entry>
    <title>PowerPointの特定のテキストボックスからテキストを取得する方法</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/202008/24_1040.html" />
    <id>tag:www.mitsue.co.jp,2020:/knowledge/blog/rpa//19.1310</id>

    <published>2020-08-24T01:40:19Z</published>
    <updated>2020-08-24T02:33:49Z</updated>

    <summary> PowerPointのスライドにあるテキストを抜き出したいとき、手動で行う場合...</summary>
    <author>
        <name>UI開発者 宇賀</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.mitsue.co.jp/knowledge/blog/rpa/">
        <![CDATA[<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20200824_01.jpg" width="924" height="484" alt=""></div>
<p>PowerPointのスライドにあるテキストを抜き出したいとき、手動で行う場合はそのテキストボックス内のテキストを選択し、コピーする作業を繰り返し行う必要があって大変ですが、UiPathを使って自動化することができます。今回は、この作業をUiPathで行う場合の方法をご紹介します。</p>
<p>準備として、PowerPointのテキストボックスの名前を確認します。</p>
<ol>
<li><p>PowerPointのウィンドウ上部にあるリボンの「ホーム」タブの「図形描画」グループにある「配置」をクリックし、表示されたリスト内の「オブジェクトの選択と表示」をクリックします。または、リボンの「ホーム」タブの「編集」グループにある「選択」をクリックし、表示されたリスト内の「オブジェクトの選択と表示」をクリックします。実行すると、ウィンドウ右側に「選択」ウィンドウが表示され、ここでスライドごとに含まれているオブジェクトの名前が確認できます。</p>
</li>
<li><p>「選択」ウィンドウが表示された状態で、中央の「スライド」ウィンドウ内の目的のテキストボックスをクリックすると、「選択」ウィンドウの該当するテキストボックスの名前が選択された状態になるので、名前を確認できます。また、名前をクリックすると変更できる状態になるので、テキストボックスの名前を変更することもできます。</p>
</li>
</ol>
<p>ここからはUiPathでのロボットのフローを説明します。</p>
<ol>
<li><p>予め確認した複数のテキストボックスの名前を配列型変数などに格納しておきます。</p>
</li>
<li><p><a href="https://docs.uipath.com/activities/lang-ja/docs/for-each">繰り返し（コレクションの各要素）（UiPath.Core.Activities.ForEach）アクティビティ</a>を使い、1.の配列型変数をコレクションに指定します。</p>
</li>
<li><p>For Each（繰り返し（コレクションの各要素））アクティビティのスコープ内で<a href="https://docs.uipath.com/activities/lang-ja/docs/get-full-text">フルテキストを取得（UiPath.Core.Activities.GetFullText）アクティビティ</a>を使います。そのセレクターを「スライド」ウィンドウのテキストボックスの要素の動的セレクターにします。具体的には、セレクターの「name」属性の部分をFor Each（繰り返し（コレクションの各要素））アクティビティのitem変数で置き換えます。注意点として、UI Explorerを開いて親要素である「スライド」ウィンドウのセレクターを追加しておく必要があります。こうすることで、UiPathが「選択」ウィンドウ内のテキストボックスの要素ではなく「スライド」ウィンドウ内のテキストが含まれるテキストボックスを指定の要素として認識します。また、出力に適当な変数を指定します。</p>
</li>
<li><p>3.で出力した変数を<a href="https://docs.uipath.com/activities/lang-ja/docs/write-line">1行を書き込み（System.Activities.Statements.WriteLine）アクティビティ</a>で出力し、テキストボックス内のテキストが出力されていることを確認します。</p>
</li>
</ol>
<p>参考として、<a href="https://docs.uipath.com/activities/lang-ja/docs/find-children">子要素を探す（UiPath.Core.Activities.FindChildren）アクティビティ</a>を使うことで、「選択」ウィンドウからテキストボックスの名前を取得する処理も自動で行うことができます。その場合、取得した子要素のコレクションをFor Each（繰り返し（コレクションの各要素））アクティビティで指定し、そのスコープの中で<a href="https://docs.uipath.com/activities/lang-ja/docs/get-attribute">属性を取得（UiPath.Core.Activities.GetAttribute）アクティビティ</a>を使い、要素の「name」属性、つまりテキストボックスの名前を取得します。後は上記と同じように、その名前をGetFullText（フルテキストを取得）アクティビティで「スライド」ウィンドウのテキストボックスの要素の動的セレクターに代入します。</p>
<p>この方法で、UiPathでPowerPointのファイルを扱うロボットを開発してみていただければ幸いです。</p>]]>
        
    </content>
</entry>

<entry>
    <title>ロボットの実行ログとして残したい情報</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/202007/29_1115.html" />
    <id>tag:www.mitsue.co.jp,2020:/knowledge/blog/rpa//19.1291</id>

    <published>2020-07-29T02:15:36Z</published>
    <updated>2020-07-29T09:04:44Z</updated>

    <summary> ロボットを扱っていて思ったように動作しないとき、どのように動いたか、どこまで処...</summary>
    <author>
        <name>UI開発者 宇賀</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.mitsue.co.jp/knowledge/blog/rpa/">
        <![CDATA[<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20200729_01.jpg" width="924" height="484" alt=""></div>

<p>ロボットを扱っていて思ったように動作しないとき、どのように動いたか、どこまで処理が進んだのかという動作の道筋を見たいときがあります。UiPathでロボットを実行した場合、自動でログファイルに情報が書き出されますが、知りたい情報によっては自分で別のファイルに書き出すほうが便利です。今回は自分用（あるいはチーム用）のロボット実行ログを書き出すにあたって、どのような情報を出力したらよいか考えてみます。UiPathを例に話を進めますが、他のRPAでも共通して使える考え方です。</p>

<p>なお、UiPathで通常「ログファイル」と言えばUiPath Studioの「ログを開く」ボタンからアクセスできる実行ログを指しますが、以下では「ロボット開発者が動作記録のために成果物とは別に書き出すファイル」を「ログファイル」と呼びます。ログファイルの書き出し形式は開発者が扱いやすい形式で構いませんが、基本的には<a href="https://docs.uipath.com/activities/lang-ja/docs/append-line">文字列を追加書き込み（UiPath.Core.Activities.AppendLine）</a>アクティビティを使ってテキストファイルに追記していく方法が便利です。</p>

<h2>実行時の状況を再現するための情報</h2>

<p>ロボットがどのような環境で何を操作したのかがわかると後で状況が再現しやすくなります。また、過去に正常に動作したときの記録があれば、エラーが起きてしまっても設定を見比べて手がかりを得ることができます。具体的には、以下のような情報を残しておくと良いでしょう。</p>]]>
        <![CDATA[<h3>ロボットが扱ったファイル</h3>

<p>ロボットが扱ったファイル（データとして参照したCSVファイルや結果を出力したExcelファイルなど）がわかるようにしておくと、設定したファイル名やファイル自体に問題がないかスムーズに調べられます。例えばログファイルの冒頭に次のような内容を記入するようにすれば、どのようなファイルを扱うロボットなのかわかりやすくなります。</p>

<pre>
参照データ: C:\path\to\data\data.csv
出力先ファイル: C:\path\to\result\result.xlsx
</pre>

<h3>パラメータの設定値</h3>

<p>ここで言うパラメータとはロボットを実行する前に設定する必要がある値を指します。例えば複数の実行モードを用意しているロボットなら、どの実行モードで実行したかの記録は必須と言えます。また、データの何行目から処理するか、処理の完了後に誰に通知メールを送るかなども設定することがあると思います。このような実行の度に異なる設定値はログとして残っていると、バグが発覚した際にも原因が調べやすくなります。パラメータの情報もログファイル冒頭に列挙しておくと良いでしょう。

<pre>
実行モード: 1
処理開始行: 5
完了メール送信先: example@example.com
</pre>

<h3>実行したプロジェクト</h3>

<p>実行したプロジェクトがある場所のパスも出力しておくと役立ちます。対象のプロジェクトをすぐに開くことができますし、実行するロボットや参照するログファイルを間違うというミスの防止にもなります。基本的には<a href="https://docs.uipath.com/activities/lang-ja/docs/get-environment-variable">環境変数を取得（UiPath.Core.Activities.GetEnvironmentVariable）</a>アクティビティでCurrentDirectoryを指定してプロジェクトのあるディレクトリを取得すると良いでしょう。</p>

<h3>マシン名</h3>

<p>マシンに依存したエラーが起きることもあるため、どのマシンで実行したかという記録も残しておいたほうが無難です。特に画像認識を行うアクティビティ（<a href="https://docs.uipath.com/activities/lang-ja/docs/click-image">画像をクリック（UiPath.Core.Activities.ClickImage）</a>アクティビティや<a href="https://docs.uipath.com/activities/lang-ja/docs/image-found">画像の存在を確認（UiPath.Core.Activities.ImageFound）</a>アクティビティなど）を使ったロボットの場合、画面解像度によって動作が安定しないことがあるので、どのマシンで動かしたのかわかったほうが良いでしょう。こちらも上記の環境変数を取得アクティビティを使い、MachineNameを指定することで取得できます。</p>


<h2>ロボットの分岐をたどる</h2>

<p>ロボットが条件分岐をどのようにたどったか分かると、バグが見つけやすくなります。分岐条件に設定ミスがあってもエラーが起きず正常終了することもあるので、おかしな挙動に気づきやすくするためにログを残しておくのがおすすめです。必ずしも全ての分岐についてのログを残さなくても良いのですが、ロボットの分岐の大まかな流れが分かるようにしておくと良いでしょう。例えば複数の実行モードを持つロボットを考えます。処理Aの実行結果がTrueだった場合に処理B、Falseだった場合に処理Cを実行するというフローを組んだとします。このときログに次のような文言があった場合、すぐに設定ミスに気づくことができます。</p>

<pre>
処理A実行完了
処理Aの結果がTrueのため、処理Cを実行
処理C実行開始
</pre>

<h2>時刻を書き込む</h2>

<p>処理が実行された時刻も記録を残しておくと便利です。全ての処理について時刻を記録する必要はありませんが、シーケンスなど処理のかたまりごとに記録しておくとロボットの各処理にかかる時間が見えやすくなります。特にループを含むロボットの場合、ループ一回にかかる時間が分かると処理全体でどのくらいの時間がかかるか予測できてロボットを運用しやすくなります。また、特定の処理にいつも以上に時間がかかっているといった問題点も見つけやすくなります。</p>

<pre>
処理A開始: 12:00
処理A終了: 12:01
処理B開始: 12:01
処理B終了: 12:06
...
</pre>

<p>以上をまとめた例が次のようなログファイルです。（もちろんこれは一例で、動かすロボットや開発者・チームが必要とする情報に応じて様々な内容や形式が考えられます。）</p>

<pre>
実行プロジェクト: C:\path\to\uipath\project1
実行マシン: RPA-001

対象ファイル
参照データ: C:\path\to\data\data.csv
出力先: C:\path\to\result\result.xlsx

設定パラメータ
実行モード: 2
処理開始行: 5
完了メール送信先: example@example.com


処理開始: 2020-07-28-12:00

処理A開始: 12:00
処理A終了: 12:01

処理Aの結果が「False」のため、処理Cを実行

処理C（ループ）の開始: 12:01
1回目終了: 12:03
2回目終了: 12:05
...
処理C（ループ）の終了: 13:03

実行モードが「2」のため、処理Dを実行

処理D開始: 13:03
処理D終了: 13:05

全処理終了: 2020-07-28-13:05
</pre>

<p>今回はロボットのログファイルに必要な情報について紹介しました。ログファイルを残せるようにロボットを開発するのは面倒なように思えますが、情報が残っていると後々のロボットの扱いやすさが格段に変わってきます。ロボットが思わぬ動作をしたときにも対処できるように、適切なログを残すようにしたいですね。</p>
]]>
    </content>
</entry>

<entry>
    <title>Workflow Inspectorを使ってみよう</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/202002/12_1030.html" />
    <id>tag:www.mitsue.co.jp,2020:/knowledge/blog/rpa//19.1176</id>

    <published>2020-02-12T01:30:46Z</published>
    <updated>2020-02-12T01:33:13Z</updated>

    <summary> 先日、UiPathコーディング規約とワークフロー品質評価キットがUiPathの...</summary>
    <author>
        <name>UI開発者 宇賀</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.mitsue.co.jp/knowledge/blog/rpa/">
        <![CDATA[<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20200210_01.jpg" width="924" height="484" alt=""></div>
<p>先日、<a href="https://www.uipath.com/ja/solutions/whitepapers/coding-standards">UiPathコーディング規約とワークフロー品質評価キット</a>がUiPathの公式サイトで公開されました。そのワークフロー品質評価キットの中に、<a href="https://go.uipath.com/ja">UiPath Go!</a>のサイトからダウンロードできる<a href="https://go.uipath.com/ja/component/workflow-inspector">Workflow Inspector</a>があります。これは、開発したプロジェクトの品質を自動で検査し、レビューをしてくれるツールです。</p>
<p>Workflow InspectorはUiPath Studioプロジェクトとして提供されていて、このプロジェクトをUiPath Studioで開いて実行し、表示されるウィンドウで評価したいプロジェクトのフォルダを指定すると、その評価レポートがExcelファイルとして出力されます（Microsoft Excelをインストールしている必要があります）。</p>
<p>チェック項目としては、</p>
<ul>
<li>命名規則違反（デフォルトでは変数及び引数がアッパーキャメルケースかどうかを判定するようです）</li>
<li>複数の同じ表示名（表示名に重複がないかどうか）</li>
<li>未使用の変数（作成した変数の中にワークフローで使用されていないものがあるかどうか）</li>
<li>必要最小限でない変数のスコープ（変数のスコープが適切かどうか）</li>
<li>不必要なシーケンスやフローチャート（空のシーケンスやフローチャートがないか、もしくは1つのアクティビティのみなのにシーケンスやフローチャートで囲っていないか）</li>
</ul>
<p>などがあり、全部で24項目あります。これらは、ダウンロードしたWorkflow Inspectorの「WorkflowInspector\Config\JP」フォルダ内にある「Checklist.xlsx」で確認や設定ができます。なお、「ワークフローの命名規則」の項目だけはデフォルトでは検査しない設定になっています。</p>
<p>レビューの結果は「WorkflowInspector\Reports」内に保存されます。この結果を見て適宜修正することでより品質の高いワークフローができます。</p>
<p>ロボットを再利用するときやチームで共有するときなどには、ロボットの可読性や保守性、安定性はより一層重要になってきます。今回ご紹介したWorkflow Inspectorを使うことでプロジェクトの品質管理がしやすくなります。そしてチーム全体でUiPathコーディング規約を理解してワークフロー品質評価キットを使うことで、プロジェクトの生産性をより向上させることができるのではないかと思います。</p>]]>
        
    </content>
</entry>

<entry>
    <title>UiPathでカスタムフォームを活用しよう</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/202001/20_1431.html" />
    <id>tag:www.mitsue.co.jp,2020:/knowledge/blog/rpa//19.1164</id>

    <published>2020-01-20T05:31:02Z</published>
    <updated>2020-01-20T06:21:36Z</updated>

    <summary> RPAロボットを開発する中で、実行の途中でユーザー（今回の場合はロボットを実行...</summary>
    <author>
        <name>UI開発者 宇賀</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.mitsue.co.jp/knowledge/blog/rpa/">
        <![CDATA[<div class="lyt_image_3"><img src="https://www.mitsue.co.jp/knowledge/blog/rpa/img/20200120.jpg" width="924" height="484" alt=""></div>
<p>RPAロボットを開発する中で、実行の途中でユーザー（今回の場合はロボットを実行している人）から入力を受け付けたい場面があると思います。<a href="https://docs.uipath.com/activities/lang-ja/docs/input-dialog">Input Dialog（入力ダイアログ）アクティビティ</a>や<a href="https://docs.uipath.com/activities/lang-ja/docs/custom-input">Custom Input（カスタム入力）アクティビティ</a>を使うこともできますが、先日、UiPath.Form.Activitiesパッケージがリリースされ、UiPathのアクティビティでカスタムフォームが作成できるようになりました。</p>
<p>カスタムフォームを作成すれば、ユーザーが入力した複数項目を対話形式で受け取ることができます。これを利用すれば、例えばロボットの実行中に何らかのIDとパスワードが必要なときに、ユーザーからの手入力で設定することがよりシンプルにできるようになったり、ほかにも、ユーザーが予めカスタムフォーム内で設定した内容でロボット内の複数の条件分岐の方向を指定すれば、その時の場面に応じたロボットのフローを実行できます。具体的にはデバッグ作業にも応用できると思います。</p>
<p>UiPath.Form.Activitiesパッケージをインストールすると、<a href="https://docs.uipath.com/activities/docs/form-activity">Create Form（フォームを作成）アクティビティ</a>が使えるようになります。出力は、アクティビティのプロパティパネルにある「フォームフィールドコレクション」でフォームに入力された情報を一つずつ変数に格納したり、「フォームフィールド出力データ」でJSON形式のデータ（String型）で一度に受け取ることができます。後者の場合は、UiPath.Web.Activitiesパッケージをインストールすれば<a href="https://docs.uipath.com/activities/lang-ja/docs/deserialize-json">Deserialize JSON（JSONをデシリアライズ）アクティビティ</a>を使ってJSONオブジェクトにできます。</p>
<p>これからはCreate Form（フォームを作成）アクティビティを活用してより使いやすいロボットを開発していきたいです。</p>]]>
        
    </content>
</entry>

<entry>
    <title>Uipathで繰り返し処理を途中再開するための工夫</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/201912/09_0926.html" />
    <id>tag:www.mitsue.co.jp,2019:/knowledge/blog/rpa//19.1134</id>

    <published>2019-12-09T00:26:44Z</published>
    <updated>2019-12-09T06:50:53Z</updated>

    <summary> RPAを使った自動化作業では、繰り返し処理を行うことがよくあります。同じ作業を...</summary>
    <author>
        <name>UI開発者 宇賀</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.mitsue.co.jp/knowledge/blog/rpa/">
        <![CDATA[<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20191206_01.png" height="405" width="773" alt=""></div>

<p>RPAを使った自動化作業では、繰り返し処理を行うことがよくあります。同じ作業を何度もするのはRPAの得意領域ですが、時には途中で想定外のパターンが生じてしまいロボットが止まってしまうということもあります。小規模の作業ならまだしも、時間のかかる作業を再度初めから動かすのはなるべく避けたいものです。ロボットが止まらない設計も大事ですが、万が一止まってしまっても途中再開がしやすい設計にすることで効率的に作業を進められます。今回は、UiPathでループを途中再開するための工夫を紹介します。</p>

<h2>扱う例</h2>

<p>Excelファイルに書かれたデータを使って、行ごとに同じ作業を繰り返す場合を考えます。例えば、商品情報が書かれたExcelファイルから各情報を拾い、CMSに入力して商品ページを作るという作業があります。今回扱う例は、Excelファイルの1行目には商品名や価格などの項目名が、2行目から100行目までは各商品の情報が書かれているものとします。</p>
<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20191206_02.png" height="214" width="786" alt=""><span class="caption">繰り返し処理で扱うExcelファイルの例</span></div>


<h2>処理がどこまで進んだかログを残す</h2>

<p>ロボットを途中再開するために最も重要なのは、処理がどこまで進んだかのログを残すことです。<a href="https://docs.uipath.com/activities/lang-ja/docs/write-cell">Write Cell（セルに書き込み）</a>アクティビティを使ってExcelファイルに逐次書き込んでもよいですし、<a href="https://docs.uipath.com/activities/lang-ja/docs/append-line">Append Line（文字列を追加書き込み）</a>アクティビティを使ってテキストファイルに追記していくのもよいでしょう。どこまで進んだか簡易的に見るだけなら、<a href="https://docs.uipath.com/activities/lang-ja/docs/write-line">Write Line（1行を書き込み）</a>アクティビティを使って出力パネルに表示するという方法もありますが、実行の記録を残すという意味ではファイルとして出力したほうが無難です。</p>
]]>
        <![CDATA[<h2>どこから再開するか指定する</h2>

<p>途中再開できるロボットを組むためには、Excelファイルのどの行から処理するかを指定する（例えば値を30と設定すればExcelファイルの30行目から処理する）変数が必要となります。ここではその変数をStartNo（Int32型）とします。StartNoを指定するには、実行前に既定値として設定するようにしてもよいですし、設定忘れを避けるために<a href="https://docs.uipath.com/activities/lang-ja/docs/input-dialog">Input Dialog（入力ダイアログ）</a>アクティビティを使って入力するようにしてもよいでしょう。</p>


<h2>Whileアクティビティを使ったループの再開</h2>

<p>途中再開できるループを組むにあたって、わかりやすいのが<a href="https://docs.uipath.com/studio/lang-ja/docs/the-while-activity">While（繰り返し（前判定））</a>アクティビティや<a href="https://docs.uipath.com/activities/lang-ja/docs/do-while">Do While（繰り返し（後判定））</a>アクティビティを使う方法です。ここではWhileアクティビティを使った例を紹介しますが、Do Whileアクティビティでも同じことができます。</p>

<p>まず、単純にExcelデータの最初の行（2行目）から最後の行（100行目）まで処理することを考えます。読み込みたい行番号をRowNo（Int32型の変数）とします。ループが始まる前にRowNoの初期値を設定（RowNo = 2）し、Whileアクティビティでは100行目まで処理するように条件（RowNo <= 100）を設定します。</p>

<p>Whileアクティビティの中には行いたい処理を配置し、RowNoの値の更新も忘れずに設定します（ループのたびにRowNoの値を1ずつ増やしていきます）。これでExcelファイルの2行目から100行目まで1行ずつ順に処理することができます。</p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20191206_03.png" height="664" width="493" alt=""><span class="caption">Whileアクティビティを使った途中再開可能なループの例。RowNoに適切な初期値を設定することでループを途中再開する</span></div>

<p>さて、この例ではExcelファイルの2行目から読み込むために、ループ前にRowNo = 2という値を設定しました。他の行から処理を始める場合も同様で、例えば51行目から処理を再開したいという場合は、ループ前にRowNo = 51と設定すれば51行目から再開できます。今回は途中再開の設定値は変数StartNoに入っているという前提なので、ループ前にRowNo = StartNoを設定すればよいでしょう。</p>


<h2>For Eachアクティビティを使ったループの再開</h2>

<p>ループを組むためのもう一つの代表的なアクティビティとして、<a href="https://docs.uipath.com/activities/lang-ja/docs/for-each">For Each（繰り返し（コレクションの各要素））</a>アクティビティがあります。このアクティビティは文字通り、配列変数などの各要素に対して処理を行うことができます。</p>

<p>Whileアクティビティのときと同様、まずは単純に2行目から100行目まで処理する場合を考えます。この場合、2, 3, 4, ..., 100という数字が入った配列を使えばよさそうです。そこで、For Eachアクティビティのコレクション値の欄に、次のような式を設定します。</p>

<pre><code>Enumerable.Range(2, 99).ToArray()</code></pre>

<p>このように書くことで、初期値2で要素数99（つまり2から100までの）の連番配列を生成できます（行番号と要素の個数を混同しないように注意）。要素の欄には変数（ここではRowNo）を設定し、プロパティのTypeArgumentはInt32に設定します。これでWhileアクティビティのときと同様にRowNoの値を2から100まで変化させてループを回すことができるようになりました。</p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20191206_04.png" height="393" width="742" alt=""><span class="caption">For Eachアクティビティを使った途中再開可能なループの例。適切なコレクション値を設定することでループを途中再開する</span></div>

<p>では、51行目から再開するにはどのように式を設定すればよいでしょうか？51行目から最後の100行目までは、50個の行が残っているので、コレクション値を次のように設定すれば実現できます。</p>

<pre><code>Enumerable.Range(51, 50).ToArray()</code></pre>

<p>途中再開するたびに残り行数を考えるのは大変なので、処理を始める行番号StartNoを使って次のように書けばStartNoの値を設定するだけで特定の行から処理を始めることができます。</p>

<pre><code>Enumerable.Range(StartNo, 101 - StartNo).ToArray</code></pre>

<p>For Eachを使った場合のループの途中再開は、Whileの場合より複雑ですが、Whileアクティビティでは扱えない<a href="https://docs.uipath.com/studio/lang-ja/docs/the-break-activity">Break（繰り返しをブレーク）</a>アクティビティや<a href="https://docs.uipath.com/activities/lang-ja/docs/continue">Continue（繰り返しをコンティニュー）</a>アクティビティが使えるというメリットがあります。</p>


<h2>DataTableの途中からループを回す</h2>

<p>上記の例ではExcelからセルの値を都度読み込む前提で話を進めましたが、<a href="https://docs.uipath.com/activities/lang-ja/docs/read-range">Read Range（範囲を読み込み）</a>アクティビティで取得したDataTableを使うという方法もあります。Read Rangeアクティビティでは範囲を指定しない場合、表全体が取得されるため、データが何行目まであるか考えなくてよいというメリットがあります。また、DataTable自体の利点としては、一度DataTableとして取得してしまえば都度ファイルを読む必要がないため<a href="https://www.mitsue.co.jp/knowledge/blog/rpa/201908/23_1513.html">処理の高速化</a>が図れる点、DataTableとして取得できるものならExcelに限らず扱える点があります。注意点としては、DataTableのインデックスは0から始まるという点があります。ここまで使ったExcelの行番号とは一致しないので気をつけてください。以下ではRowNoとStartNoはExcelの行番号ではなくDataTableの行インデックスを表しています。</p>

<p>以下の例で扱うDataTable型の変数をProductDataとします（ExcelファイルをRead Rangeアクティビティ（ヘッダーあり指定）で読み込んだDataTableです）。DataTableをループするときに最もよく使われるのは<a href="https://docs.uipath.com/activities/lang-ja/docs/for-each-row">For Each Row（繰り返し（各行））</a>アクティビティでしょう。このアクティビティでも工夫次第で途中再開できるように組むことができます。</p>

<p>例えば、For Each Rowアクティビティ内で現在のインデックスを変数RowNoに出力し、処理を始めたい行のインデックスよりもRowNoが小さい場合はContinueアクティビティを使ってスキップするという方法があります。</p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20191206_05.png" height="640" width="855" alt=""><span class="caption">For Each Rowアクティビティを使った途中再開可能なループの例。特定の行に達するまで、Continueアクティビティを使って処理を飛ばす</span></div>

<p>DataTableのループは基本的にはFor Each Rowアクティビティを使えば十分ですが、行インデックスを直接指定する形でループしたい場合は（Do）WhileアクティビティやForEachアクティビティを使います。行インデックスを使ってDataTableの特定の要素を取り出す方法ですが、例えばProductDataから特定の行RowNoに書かれている商品名を取得したければ次のように書きます。</p>

<pre><code>ProductData.Rows(RowNo).Item("商品名").ToString()</code></pre>

<p>また、ProductData全体の行数は次のように取得できます。</p>

<pre><code>ProductData.Rows.Count</code></pre>

<p>あとは基本的には初めに示したWhileアクティビティやFor Eachアクティビティと同じようにループの設定をすればよいのですが、DataTableのインデックスは0始まりのため、設定する式が少し変わる点に注意が必要です。例えばWhileアクティビティの条件は次のようになります。</p>

<pre><code>RowNo < ProductData.Rows.Count</code></pre>

<p>For Eachアクティビティの場合はコレクション値を次のように設定します。</p>

<pre><code>Enumerable.Range(StartNo, ProductData.Rows.Count - StartNo).ToArray()</code></pre>


<p>今回は、UiPathでループを途中再開する方法を紹介しました。中には複雑な方法もありましたが、ループの再開ができるとロボットはかなり扱いやすくなります。スムーズに再開できるための仕組みを心がけてロボットを開発していきたいですね。</p>
]]>
    </content>
</entry>

<entry>
    <title>UiPath高速化の工夫（フローチャートの構造編）</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/201908/23_1513.html" />
    <id>tag:www.mitsue.co.jp,2019:/knowledge/blog/rpa//19.1058</id>

    <published>2019-08-23T06:13:57Z</published>
    <updated>2019-08-23T07:44:10Z</updated>

    <summary> RPAを用いた業務自動化において、処理にどのくらい時間がかかるかというのはとて...</summary>
    <author>
        <name>UI開発者 宇賀</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.mitsue.co.jp/knowledge/blog/rpa/">
        <![CDATA[<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190823_01.png" height="405" width="773" alt=""></div>

<p>RPAを用いた業務自動化において、処理にどのくらい時間がかかるかというのはとても重要な点です。
特に、手順が多く処理に時間がかかる場合、「もっと早く処理が終わるといいけど、どのようにロボットを変えたら良いかわからない」ということも多いのではないでしょうか？
このBlogでも以前<a href="https://www.mitsue.co.jp/knowledge/blog/rpa/201808/28_1435.html">UiPathを高速化するための工夫</a>を紹介しました。
その中でも特に重要なのが、「無駄な処理を行っていないか、手順を見直す」というポイントでした。
今回はさらに一歩踏み込んで、「無駄になり得る処理を効果的に減らす方法」、つまり状況によって必要だったり必要でなかったりする処理を扱うための方法を考えてみます。
UiPathの画面を例として示していますが、フローチャートの構造そのものを扱うのでRPA全般に共通する話でもあります。</p>
]]>
        <![CDATA[<h2>ループでは必要に応じてbreakやcontinueを使う</h2>

<p>Excelから読み込んだデータの処理やWebからデータを取り込む場合など、ロボットで繰り返しの処理を行うことはよくあると思います。
しかしときにはループを最後まで回す必要がなかったり、特定の繰り返し処理を飛ばしたかったりする場合があります。
そのようなときに使うのが<a href="https://docs.uipath.com/studio/lang-ja/docs/the-break-activity">Break（繰り返しをブレーク）</a>アクティビティや
<a href="https://docs.uipath.com/activities/lang-ja/docs/continue">Continue（繰り返しをコンティニュー）</a>アクティビティです。
いずれも<a href="https://docs.uipath.com/activities/lang-ja/docs/for-each">For Each（繰り返し（コレクションの各要素））</a>アクティビティや
<a href="https://docs.uipath.com/activities/lang-ja/docs/for-each-row">For Each Row（繰り返し（各行））</a>アクティビティ内で使うことのできるアクティビティです。</p>

<p>Breakアクティビティはループから抜けるために使います。
例えば「1000個のデータから特定の条件を満たすデータを1つ見つける」というフローを考えます。
このフローで300個目に条件を満たすデータを見つけたので残りの700個のデータは見る必要がないという場合、
データを見つけた時点でループを抜けるようにフローを組んでおけば、残りのデータを調べずに済みます。</p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190823_02.png" height="738" width="583" alt=""><span class="caption">
条件を満たした時点でBreak（繰り返しをブレーク）アクティビティが実行され、ループ処理は終了する</span></div>

<p>Continueアクティビティはループ内の処理を飛ばしたいときに使います。
例えば「1000個のデータを処理したいが、特定の条件に当てはまるデータは無視したい」というフローを考えます。
この場合、条件によってContinueが実行されるようにフローを組んでおけば、必要なときのみ処理が実行されます。</p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190823_03.png" height="738" width="583" alt=""><span class="caption">
Continue（繰り返しをコンティニュー）アクティビティが実行されたときは、それ以降の処理はスキップされる</span></div>

<p>ただし、UiPathの場合このBreakアクティビティとContinueアクティビティが使えるのは、For EachアクティビティとFor Each Rowアクティビティ内のみです。
そのため、<a href="https://docs.uipath.com/studio/lang-ja/docs/the-while-activity">While（繰り返し（前判定））</a>アクティビティや
<a href="https://docs.uipath.com/activities/lang-ja/docs/do-while">Do While（繰り返し（後判定））</a>アクティビティで同様の動作をさせたい場合、
あえてループ条件から外れる設定をすることでBreakの代わりにしたり、
処理をする場合としない場合に条件分岐することでContinueの代わりにしたりする工夫が必要になります。</p>

<h2>複数の条件による分岐の構造を工夫する</h2>

<p>「条件Aと条件Bが両方成り立つときに処理Cをし、それ以外の場合処理Dをする」という場合を考えます。
例えばある商品について「『商品ページから価格等の情報を取得できた』かつ『商品リスト（Excelファイル）に情報が掲載されていた』ときに、
『情報を比較してレポートを出力する』それ以外の場合は『比較ができない旨を出力する』」という場合です。
この場合、次の図のように条件Aを判断するための処理と条件Bを判断するための処理をし
（それぞれ結果は<a href="https://docs.microsoft.com/ja-jp/dotnet/visual-basic/language-reference/data-types/boolean-data-type">boolean型</a>の変数result_A、result_Bとして出力されるものとします）、
「result_A And result_B」の真偽で処理Cと処理Dに振り分ければ良さそうです。<p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190823_04.png" height="639" width="616" alt=""></div>

<p>しかし、このフローチャートはもっと効率が良い構造に変更することができます。
よく考えると、ここでは「条件Aと条件Bが両方成り立つ」かどうかを知りたいだけなので、
条件Aが成り立たないとわかった時点で条件Bが成り立つかどうかは調べる必要はありません。
そのため条件Aが成り立たない時点で処理Dに割り振ることができ、フローチャートは次の図のように改善できます。</p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190823_05.png" height="656" width="642" alt=""></div>

<p>もとのフローでは条件Aと条件Bを調べるための処理が両方とも毎回呼び出されていましたが、
改善したフローチャートでは、条件Bを調べるための処理は必要なときのみ呼び出されるので無駄を省略できることがわかります。</p>

<p>また、「条件Aと条件Bのどちらか一方でも成り立つときに処理Cをし、それ以外の場合処理Dをする」という場合、
つまり「result_A Or result_B」の真偽で処理Cと処理Dに振り分けたいときも同じように考えることができます。
この場合、result_Aの値がTrueだとわかった時点でresult_Bの真偽は調べる必要がないため、次のようなフローチャートになります。</p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190823_06.png" height="656" width="672" alt=""></div>

<p>今回は、条件によっては無駄になりうるフローを減らすという観点でフローチャートの構造を改善する方法を紹介しました。
ロボットの改善点を考えるときに、ループや条件分岐が多くあると複雑に感じるかもしれませんが、
その分無駄な処理を減らすチャンスが多いとも言えます。
条件ごとにどこまでの処理が必要なのか考えて、適切にフローを組んでいきたいですね。</p>]]>
    </content>
</entry>

<entry>
    <title>UiPathで呼び出し先のロボットからファイルを参照する</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/201906/21_1216.html" />
    <id>tag:www.mitsue.co.jp,2019:/knowledge/blog/rpa//19.1017</id>

    <published>2019-06-21T03:16:53Z</published>
    <updated>2019-06-21T08:15:33Z</updated>

    <summary> ロボットを動作させるとき、Excelファイルやテキストファイルなど、何らかの外...</summary>
    <author>
        <name>UI開発者 宇賀</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.mitsue.co.jp/knowledge/blog/rpa/">
        <![CDATA[<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20191621_01.jpg" height="405" width="773" alt=""></div>
<p>ロボットを動作させるとき、Excelファイルやテキストファイルなど、何らかの外部ファイルを参照するシーンがよくあります。
UiPathで外部ファイルを参照するには、適切なアクティビティに適切なファイルパスを渡せばよいのですが、<a href="https://activities.uipath.com/lang-ja/docs/invoke-workflow-file">Invoke Workflow File（ワークフローファイルを呼び出し）</a>アクティビティで呼び出されたアクティビティからファイルを参照する際にはパスの扱いに注意が必要な点があります。
今回は、UiPathで呼び出し先のロボットからファイルを参照する方法について考えてみます。</p>

<p>ロボットから外部ファイルを参照するとき、ファイルが置かれている場所をフルパスで考えたほうがわかりやすい場合と、ロボットから見た相対的な位置（相対パス）で考えたほうがわかりやすい場合があります。
例えば、共有フォルダにあるExcelファイルをロボットで編集するなどの場合は、参照したいファイルの置き場所をフルパスで記述してロボットに参照させることが多いと思います。
一方で、ロボットを動作させる上で一時ファイルを書き出したり、スクリプトを実行したりするということもあります。
このようなロボットの一部とも言えるファイルは、ロボットから見た相対パスで参照する場所を考えたほうが都合がよいことが多いです。</p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190621_02.png" height="366" width="731" alt=""><span class="caption">スクリプトなどロボットの動作を補助するファイルを含んだプロジェクトの場合、参照するファイルの場所は相対パスで考えたほうがわかりやすい</span></div>]]>
        <![CDATA[<p>しかし、相対パスでファイルを参照しているロボットを別のロボットから呼び出す場合、注意が必要な点があります。
それは、呼び出し先のロボットから見た相対パスでファイルパスを記述しても、実行時には呼び出し元のロボットから見たファイルパスで解釈されるという点です。例えば図のように、何らかのスクリプトを読み込むロボット「read.xaml」と、「read.xaml」を呼び出すロボット「Main.xaml」を考えます。(このとき、「read.xaml」と「Main.xaml」はそれぞれ別のフォルダに置かれているものとします。)</p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190621_03.png" height="297" width="753" alt=""><span class="caption">スクリプトを読み込むread.xaml(左)と、read.xamlを呼び出すMain.xaml（右）。このままMain.xamlを実行してもスクリプトは正しく参照されない。
</span></div>

<p>「read.xaml」は、<a href="https://activities.uipath.com/lang-ja/docs/read-text-file">Read Text File（テキストファイルを読み込む）</a>アクティビティでファイル名に「.\script\script1.js」を指定することで、同じフォルダ内にある「script」フォルダの中の「script1.js」ファイルを読み込んでいます。
この状態で「read.xaml」を直接実行すると、問題なく動作します。
一方でこのロボットを呼び出す「Main.xaml」を実行するとエラーとなってしまいます。
パス「.\script\script1.js」が「Main.xaml」から見たパスとして解釈されてしまい、本来読み込もうとしていたスクリプトが参照できないためです。</p>


<p>このような事態を避けるためには、呼び出し先のロボットが置かれているフォルダを取得できればよさそうです。
ロボットが置かれているフォルダは、<a href="https://activities.uipath.com/lang-ja/docs/get-environment-variable">Get Environmental Variable（環境変数を取得）</a>アクティビティを使って取得できますが、この場合も問題は変わらず、呼び出し元のロボットがあるフォルダが取得されてしまいます。
そこで、ロボットを呼び出す際に呼び出し先のロボットがあるディレクトリのパスを渡すという方法をとります。
上記の例で言えば、「read.xaml」はフォルダ「D:\robot\read\」内にあるので、このパスを引数（図では「currentDir」）に渡し、「read.xaml」内でcurrentDirとそれに続くパス「script\script.js」を結合するようにします。
このとき、currentDirのデフォルト値には「.\」を入れておきます。こうすることで、「read.xaml」を直接実行した場合も、「Main.xaml」から呼び出した場合も正しく「script1.js」を参照することができます。
ファイルの参照方法としてはフルパスですが、呼び出し先のロボットを開発するときには相対パスだけを考えればよいというメリットがあります。</p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190621_04.png" height="355" width="739" alt=""><span class="caption">呼び出し元のロボットでは、呼び出し先のロボットが置かれているフォルダのパスを設定する</span></div>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190621_05.png" height="151" width="658" alt=""><span class="caption">呼び出し先のロボットではフォルダパスを受け取る引数の既定値として「.\」を設定する</span></div>

<p>また、パスを結合する際には、<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.io.path.combine?view=netframework-4.8">Path.Combine</a>メソッドが便利です。このメソッドを使うと、フォルダ名の後ろが\で終わっているかどうかにかかわらず、適切にパスを結合できます。
（Path.CombineはアクティビティではなくVB.NETのメソッドです。UiPath内でVB.NETの表現を使うことについて、詳しくは<a href="https://www.mitsue.co.jp/knowledge/blog/rpa/201809/11_1807.html">こちら</a>の記事をご覧ください。）</p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190621_06.png" height="306" width="482" alt=""><span class="caption">Path.Combineメソッドを使うとファイルパスの結合が簡単にできる</span></div>

<p>今回は、UiPathで呼び出し先のロボットからファイルを参照するときの注意点を紹介しました。
「直接実行していたときには問題なかったのに、別のロボットから呼び出そうとすると動作しない！」という事態に陥らないために、適切にファイルパスの設定をしたいですね。</p>
]]>
    </content>
</entry>

<entry>
    <title>UiPathで引数の値をどう管理するか？</title>
    <link rel="alternate" type="text/html" href="https://www.mitsue.co.jp/knowledge/blog/rpa/201904/23_1646.html" />
    <id>tag:www.mitsue.co.jp,2019:/knowledge/blog/rpa//19.977</id>

    <published>2019-04-23T07:46:09Z</published>
    <updated>2019-04-24T02:11:40Z</updated>

    <summary> ロボットを開発して作業を自動化すると、あとは実行ボタンを押すだけで目的の処理を...</summary>
    <author>
        <name>UI開発者 宇賀</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="https://www.mitsue.co.jp/knowledge/blog/rpa/">
        <![CDATA[<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190423_01.jpg" height="405" width="773" alt=""></div>
<p>ロボットを開発して作業を自動化すると、あとは実行ボタンを押すだけで目的の処理を実行することができます。
しかし時には、今までと異なるExcelファイルを読み込みたい、書類に入力する日付を都度変えたいなど、ロボットを実行する前に変数の値を設定したい場合があります。
実行前に設定する機会や項目が多くなると、設定し忘れたり誤った値を設定してしまったりすることもあるかもしれません。
今回は、UiPathで初期値の設定が必要な変数（引数）をどう管理するかについて考えてみます。</p>

<h2>外部からロボットに渡す値は引数として定義する</h2>

<p>ロボット内のアクティビティ間で渡す値を変数と呼びますが、その中でも特に外部からロボットに渡す値を引数と呼びます。今回設定するのも、ロボットの実行時に設定しておく必要がある値（=ロボットの外部から管理したい値）なので引数と言えます。まず、引数は引数であることが分かるように設定しておきましょう。UiPathの引数はデザイナーパネルで「変数」の横にある「引数」の項目で設定できます。引数の使い方は基本的に変数と同じで、各種アクティビティ内で使うことができます。通常の変数との違いは、引数として設定することで、他のロボット（ワークフローファイル）とやり取りする値として使うことができるという点です。今回紹介する例ではロボット間の値の受け渡しは行わないので、全て通常の変数として設定しても問題はないのですが、今後の拡張性やロボットとしての見通しのよさを考えると、外部から渡す値は引数として設定したほうがよいでしょう。</p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190423_02.png" height="600" width="900" alt=""><span class="caption">デザイナーパネルで、「変数」の横にある「引数」の項目を使って引数を定義できる</span></div>]]>
        <![CDATA[<h2>入力ダイアログを使う</h2>

<p>さて、変数と引数を分けて設定することで、ロボット実行前に設定しなければならない値がどれなのかひと目で分かるようになりました。これでどの値を設定したらよいか迷うこともなくなりそうです。
しかし、引数の値を頻繁に変える必要がある場合、毎回UiPath Studioを起動して値を編集するのは面倒ですし、値を設定し忘れる可能性もあります。また、ロボットを実行する人が必ずしもロボットを編集できるとは限りません。
できればロボット自体を編集することなく外部から値を渡したいところです。</p>

<p>外部から値を渡す簡単な方法として、<a href="https://activities.uipath.com/lang-ja/docs/input-dialog">Input Dialog（入力ダイアログ）</a>アクティビティがあります。このアクティビティでは入力フィールドのあるダイアログボックスを表示し、ユーザーが入力した値を読み取ってロボットに渡すことができます。
引数の個数が少なく、頻繁に値を変えたい場合はInput Dialogアクティビティを使うとよいでしょう。</p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190423_03.png" height="641" width="900" alt=""><span class="caption">頻繁に変える必要がある引数の場合、Input Dialogアクティビティを使うとロボット実行時に忘れずに値を設定できる</span></div>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190423_04.png" height="176" width="336" alt=""><span class="caption">Input Dialogアクティビティによる入力画面</span></div>

<h2>Excelで値を管理する</h2>

<p>一方、引数の個数が多かったり、毎回値を変えるわけではない場合はInput Dialogによる設定は煩わしいかもしれません。その場合はExcelファイルで引数を管理するという方法があります。
例えばA列に項目名、B列に読み込みたい値を記入するなどのルールを決め、Read Cell（セルを読み込む）アクティビティで値を読み取れるように設定しておけば、必要なときにExcelファイルを編集するだけでロボットに渡す値を変えることができます（ただし<a href="https://www.mitsue.co.jp/knowledge/blog/rpa/201903/25_1545.html">こちらの記事</a>で触れたように、セルの表示形式と引数の型には注意が必要です）。</p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190423_05.png" height="131" width="425" alt=""><span class="caption">ロボットだけで完結させず、Excelファイルを使って変数の値を管理するという方法もある</span></div>

<h2>JSONで値を管理する</h2>

<p>Excel以外にも外部ファイルから値を渡す方法として、JSONファイルを使った方法があります。
JSONファイルはメモ帳等のテキストエディタで編集できます。例えば上記のExcelと同様の値を設定したかったら、</p>

<pre>
<code>
{"テンプレート": "D:\\template\\template03.txt", "データ": "D:\\data\\data2019.txt", "ログ保存先": "D:\\log\\"}
</code>
</pre>

<p>と書かれたJSONファイル（拡張子が.jsonのテキスト）を用意します("\"はエスケープする必要があるので"\\"となっています)。
このJSONファイルをUiPathで読み込むために、<a href="https://activities.uipath.com/lang-ja/docs/deserialize-json">Deserialize JSON（JSONをデシリアライズ）</a>というアクティビティを使います。このアクティビティはUiPath.Web.Activitiesというパッケージをインストールすると使えるようになります（<a href="https://studio.uipath.com/lang-ja/docs/managing-activities-packages">パッケージを管理</a>）。
JSONを読み込む手順としては、まず<a href="https://activities.uipath.com/lang-ja/docs/read-text-file">Read Text File（テキストファイルを読み込む）</a>アクティビティでJSONのテキストをString型の変数（仮にjson_textとする）として読み込みます。続いてこのjson_textをDeserialize JSONアクティビティに渡すと、json_textがJSONとして解釈された変数（仮にjson_objectとする）が得られます。あとは、GetValue()メソッドを使ってほしい値を取り出します。例えば「ログ保存先」の値が欲しければ、json_object.GetValue("ログ保存先").ToString()とすることで値を取得できます。</p>

<div class="lyt_image_3"><img src="/knowledge/blog/rpa/img/20190423_06.png" height="704" width="900" alt=""><span class="caption">Deserialize JSONアクティビティを使うと、ロボットに渡す値をJSONファイルで管理できる</span></div>

<p>いかがでしたか？ExcelやJSONといった外部ファイルを使った引数管理では、今回の例のように値を設定しやすいだけでなく、別のロボットで同じ値の設定を引き継げるという利点もあります。
最初に外部から値を読み込む設定をするのは少し面倒かもしれませんが、一度設定すればその後のロボットの管理がとても楽になります。あとから変えるかもしれない値をどう管理すればミスが生じにくくなるかという点を意識してロボット開発をしていきたいですね。</p>



]]>
    </content>
</entry>

</feed>
