【RPA例題】Salesforce上で特定顧客のリードが入力済みかどうかを判定する

[Salesforce からWebスクレイピングでデータを抜き出す](https://qiita.com/Okura_/items/04b1c8cc7c195c2f95d7)方法を使って、業務に即した応用編のBotを作ってみましょう。マーケティング業務では、CRMにリードを入れていきますが、特定の顧客のリードが過去すでに入力されているかどうかを作業前に簡単に判別したいというニーズがあります。これを以下の前提のもとRPA (Automation Anywhere Community Edition, AACE)で作ってみたいと思います。

前提

* API連携すればいいかもしれないが、現場のユーザーなのでそれができない、面倒くさい
* RPAを実行するユーザーは、担当する顧客のデータはCRM上で見られる権限を持っているものとする
* 細かいことをいうと、リードの「会社名」フィールドの中を見なければならないが、リードの件名なども含めて顧客名の文字列がヒットすれば該当したものが見つかったとする

これを元に、SalesforceをClassic+Accessibility modeで表示させ、Webスクレイピングで判定することにします。

# 基本設計の考え方
Salesforce Classic modeでは、リードのみのキーワード検索を行う画面のURLを指定できます。検索キーワードもURLに引数として持たせられるので、これを使うのが一番簡単と思い、さっそく考えてみました。

```
https://<テナント名>.my.salesforce.com/_ui/search/ui/UnifiedSearchResults?searchType=2&sen=003&sen=0F9&sen=005&sen=006&sen=701&sen=0TO&sen=00O&str=<検索文字列>#!/str=<検索文字列>&initialViewMode=detail&fen=00Q&collapse=1&searchAll=true

```

<検索文字列>に、Salesforce内でヒットする文字列とヒットなしの文字列を入れてみると、以下のように画面結果が表示されます。

ヒットあり (例: aa)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/4c467e2f-189c-cb9e-79b6-192c70863687.png)

ヒットなし (例: zzzzz)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/c2ff2762-05ad-90fd-c63b-a85e3d0b797e.png)


ヒットありの場合の画面でExtract Tableコマンドで検索結果のテーブルを抜いてくるアクションリストを作り、<検索文字列>の部分を変数にして最初にユーザー入力を求めるようにすればうまくいきそうですね！あとはテーブルがない場合のエラー処理をしたり、微調整をすることでうまくいきそうです。


# ここで課題が...
...と思ったのですが、思わぬところで課題が出てきました。
リードの「会社名」に指定したい文字列は通常は日本語 (2バイト文字)なのですが、Internet Explorer (IE)でURLの引数にエンコードされていない2バイト文字を直接指定ができないのです！(この問題は英語では発生しません) 仮に指定しまうと HTTP 400 Error (正しくない要求) エラーになります。

日本語をURL Encodeした文字列 (例: 日本語 → `%E6%97%A5%E6%9C%AC%E8%AA%9E`)を指定すればIEでいけるのですが、AAには残念ながらURL Encodeを行うコマンドがありません。Bot Storeも探してみたのですがなさそうでした。

Chromeなど他のブラウザーであればURLの引数に直接日本語を指定できるのですが、今度はExtract TableコマンドがIE以外に非対応でした。

ということで状況をまとめると、以下の困難が立ちはだかってしまいました。

* **Internet Explorer で引数に日本語を設定できない (URL Encodeが必要)**
* **AAにはURL Encodeコマンドがない**
* **テーブルデータの抜き出しはChrome上ではできない (Extract Table非対応、Object Cloningには機能がない)**

このような、それぞれちょとずつ足りない状況のパズルをうまく解く必要がありました。

# 解決方法
そこで、いったん、ヒットありの1バイト文字でヒットありの画面を出した後、この検索ボックスをキャプチャして実際に検索したい会社名を入力して再検索を実行し、その結果のテーブルを取得する、ということにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/0b02008b-08ee-03a6-4bf1-2fd94e3153b7.png)

キャプチャの方法はWeb Recorder/Manage Web Controlsと、Object Cloningの2種類を試しました。Object Cloningだと、なぜか周りの`DIV`タグが認識されてしまうのに対し、Web RecorderだとText Boxを正しく認識してくれました。参考までに、解析したこのテキストボックスの周りのHTMLタグの情報を添えておきます。

```HTML:
<td class="searchResultsCell">
  <div id="secondSearchDiv">
    <form id="secondSearchForm">
      <div class="search2TextInputContainer">
        <input id="secondSearchText" maxlength="100" type="text" value title="検索...">
      </div>
      <div class="search2SubmitBtnContainer">
        <input type="submit" id="secondSearchButton" class="btn" value="再検索">
        <span class="search2InfoIconContainer">...</span>
      </div>
      <div class="searchMoreOptions" id="searchMoreOptions" style="visibility: visible;">...</div>
      <div style="visibility: hidden; top: -78px;" class="searchMoreOptionsOverlay" id="searchMoreOptionsOverlay">...</div>
      <div style="clear: both;"></div>
    </form>
  </div>
  <div id="searchBody">...</div>
</td>

```

**Object Cloning** <font color="Red">(うまくいかなかった)</font>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/bc4bb907-ba1b-33b3-a327-afd915897ed3.png)


**Web Recorder/Manage Web Controls** <font color="Green">(うまくいった！)</font>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/c11eee9a-f15e-9f6d-7931-2e03a30515ea.png)

**Web Recorder/Manage Web ControlsのAdvanced Viewのオプション:** Page URLについているチェックは外し、Set Textのアクションのテキストは、入力したい会社名 (実際には変数を入れて置き別の場所で指定)で置き換える
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/249515d2-9729-fa1c-1b64-2eb714abd6bc.png)


# アクションリストの組み立て
組み立てたいアクションリストは以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/53d3b1bf-4c5e-4f56-a625-4ec8aaad4dc0.png)

### Web Recorderによる記録
組み立て方としては、まず11行目にあるWeb Recorder/Extract Tableコマンドを、まずWeb Recorderでレコーディングするところから始めるのが良いです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/b0e6550f-fde4-3d69-1004-7b26c5c405e9.png)

あらかじめ別途SalesforceにIEでログインした状態で、リードの検索結果がヒットありになるURLを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/6eaf2ad1-b361-8c55-f8ee-8c6826eb619a.png)

以下のダイアログボックスの後、URLがIEで開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/ee4e3dac-a7af-226e-1096-79595c51c678.png)

IEが開いた状態で、Extract Tableをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/b7fec1c9-c1dd-2683-e8c6-f5f42e7a9d05.png)

その後、以下のテーブル部分がキャプチャできるようにマウスを操作してクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/99d32e28-7662-08c9-f7a9-11e434b279c5.png)

うまくキャプチャできると、Previewにテーブルの内容が取得されたダイアログボックスが開きます。問題なければNextを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/66f45ac8-85a7-0588-784a-59842e549733.png)

7番という番号のテーブルがキャプチャされたと表示されました。あとは、これを出力するCSVファイルのパスを記入します。デスクトップに出力するために、`$vResultFile$`という変数をあらかじめ作っておき、これを入力します。`$vResultFile$`には、`$System(USERPROFILE)$\desktop\sfdc_leads.csv`という値を入れておきましょう。これで、デスクトップにsfdc_leads.csvというファイルが作成されます。その後、Finishを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/24725f7f-7ca3-1b51-a44c-019481fa903c.png)

そして、ツールバーのStop Recordingをクリックすると完成です。好きな名前でタスクを保存してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/a627b758-394e-5d5e-fe25-ca4d93766603.png)

### Web Recorder関連コマンドのプロパティ編集
タスクを編集モードで開くと、7行目のOpen Browserコマンドと11行目のExtract Tableコマンドにあたる2行が表示されます。

まず、Open Browserコマンドを選択して、Editをクリックします。実際のIEウィンドウの判定はPage URLは検索文字列によってかわるのでチェックボックスを外し、Page Titleはドロップダウンリストで「検索結果 ~ Salesforce - Unlimited Edition」(Salesforceのエディションで若干違うかもしれませんが)を選択して、チェックボックスをONにしてSaveします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/aa8611b3-b916-0f01-d398-95ff15d6e438.png)


次に、Extract Tableコマンドを選択して、Editをクリックします。Advanced Viewを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/fc02e333-01ea-266f-7d41-cc4d1606a5d5.png)
この中で、「On Error continue with next action」のチェックボックスをONにします。こうすることで、検索結果ヒットなしの場合に該当するテーブルがなくエラーになるところのエラー処理を行うことができます。また、先ほどと同様に、Page URLのチェックボックスを外します。

### 顧客名の入力ダイアログボックスの実装
次に、2行目のプロンプトダイアログボックス (Prompt for Valueコマンド)を追加します。ウィンドウはDon't Write In Any Windowを選択して、結果は`$Prompt-Assignment$`変数に代入します。

### 結果の再検索を実装
そして、8-9行目の、検索ボックスへの文字列入力と再検索ボタンのクリックを実装します。これは前述のようにWeb Recorder/Manage Web Controlsコマンドを使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/0b02008b-08ee-03a6-4bf1-2fd94e3153b7.png)

### ウェイト、CSVファイルの削除処理、Excelでのオープン処理などを加えて完成!!
後は、詳細は省きますが、検索結果が見つかれば最後にExcelを開いたり、あらかじめCSVファイルを削除しておくといったコマンドを追加して整えると、一応の完成です。

# より実用的にするための実装
Excelファイルにあらかじめ顧客名一覧を用意しておき、検索結果あり/なしをそのExcelに書き込む、といった形で最終的に実装できれば、より実用的かもしれません。

一応、それを実装したアクションリストも以下に挙げておきます。ご参考まで！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/ef3f3da6-6b49-4997-af7d-e828a27d81de.png)

入力時に指定するExcelファイルには、A列の2行目以降に、リードの識別子になるもの (電子メールアドレスが一番ユニーク性がある)を指定しておきます。

<table>
<tr><th></th><th style="text-align:center;">A</th><th style="text-align:center;">B</th></tr>
<tr><th>1</th><td><b>List</b></td><td><b>Result</b></td></tr>
<tr><th>2</th><td>test1@example.com</td><td><font color="#cccccc">Yes or 空白&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></td></tr>
<tr><th>3</th><td>test2@example.co.jp</td><td><font color="#cccccc">Yes or 空白</font></td></tr>
<tr><th>4</th><td>test3@sample.com</td><td><font color="#cccccc">Yes or 空白</font></td></tr>
<tr><th>5</th><td>test4@test-company.jp</td><td><font color="#cccccc">Yes or 空白</font></td></tr>
<tr><th>6</th><td>test5@abc-test.jp</td><td><font color="#cccccc">Yes or 空白</font></td></tr>
<tr><th>7</th><td>test6@example.net</td><td><font color="#cccccc">Yes or 空白</font></td></tr>
</table>