[Salesforce®初心者でもできる!UiPathによるオペレーションの自動化] Vol.16

Salesforce-main

複合一括リクエスト

前回は予定の二重登録の解消に効く、 「行動(Event)とToDo(Task)の操作」するワークフローについてご紹介しました。もし見逃したという方は「行動(Event)とToDo(Task)の操作」も併せてご覧ください。

ロボットでまとまった量のデータを一括登録している。通常は気にならないが、件数が多いピーク時はSalesforce契約上のAPIの呼び出し回数枠を超えてしまい登録できない・・・。

この様な、まとまったデータを処理した場合に起きる「API呼び出し回数制約」に悩まれたことはないでしょうか。

今回は、 API呼び出し回数を節約するワークフローをお届けします。

  • 価格情報1000件の一括登録

読み終えたあと、本記事をみながらワークフローを作成すれば回数を節約できると思います。

価格情報1000件の一括登録

1000件の価格元情報をSalesforceの価格表に40回のAPI呼び出し(総件数の1/25回)で登録するワークフローを作成します。はじめに商品および価格関連のオブジェクト構造を説明します。

Salesforce-Integration_vol16_image1

「商品」は商品名やコードといった売価以外の商品情報を管理します。「価格表」は定価やキャンペーンなど販売パターンの名称を管理します。各価格表に含まれる商品と単価は「価格表エントリ」が管理します。

価格元情報と登録結果イメージ、並びにワークフローの全体像は次の通りです。

Salesforce-Integration_vol16_image2
Salesforce-Integration_vol16_image2_2
Salesforce-Integration_vol16_image3

本例は商品が予め登録されていることを前提とし、価格表を新規登録と価格表エントリの一括登録を行います。

商品がSalesforceに登録されていない場合はWeb画面から準備してください。

Activityの設定方法を中心にお届けしているため、Salesforceアプリケーションスコープの設定やエラー制御は含まれておりません。また、Excelへの出力部分の実装は解説を割愛しておりますのでご了承ください。

個別にプロパティの設定内容を見てみます。

①価格元情報を読み込みます。
Salesforce-Integration_vol16_image4

①-1 読み込んだ一覧を格納する変数を設定します。

  • 変数名は任意でOKです。本例では「priceList」を設定します。

※その他プロパティは図の通りとします。

②各商品のIDを特定するため商品一覧を取得します。
Salesforce-Integration_vol16_image5
②-1 SOQL詳細:

SELECT Id,ProductCode FROM Product2 WHERE IsActive = True

  • Id,ProductCode(商品コード)を商品(Product2)オブジェクトから取得するSOQLです

  • レコードの絞込条件として、

    • 有効な商品であること

    を指定しています。

②-2 Salesforceステータスは必要に応じて設定します。

※本例では設定していますが、後続では使用しません。

②-3 SOQLの結果を格納するため変数を設定します。

  • 変数の型はDataTableです。

  • DataTable内の列はSELECTの項目名になるため、Id,ProductCodeの2列になります。

③価格元情報にSalesforce商品一覧を結合し、各商品ごとにレコードのIDを対応付けます。
Salesforce-Integration_vol16_image6

③-1 結合前データ:価格元情報 を設定します。

  • 本例では①で読み込んだ「priceList」を設定します。

③-2 結合前データ:Salesforceの商品一覧 を設定します。

  • 本例では②で取得した「sfdcProductList」を設定します。

③-3 結合後データを格納する変数を設定します。

  • 変数名は任意でOKです。

③-4 結合方法「Inner」を選択します。

③-5 結合時に比べる列を指定します。

  • 本例では「商品コード」と「ProductCode」を設定します。

④価格表を新規に登録します。
Salesforce-Integration_vol16_image7

④-1 登録対象オブジェクト「Pricebook2」を選択します。

④-2 登録対象の項目を選択する子ウインドウを開き、次の項目を選択します。

-Name(価格表名),IsActivite(有効)

④-3 各項目に登録する値を設定します。

  • Idは新規登録されたレコードのIDを格納する変数を設定します。変数名は任意でOKです。

  • Name(価格表名)は価格表の名前を設定します。名称は任意でOKです。

  • IsActive(有効)は新規登録した価格表を有効とするか否かを設定します。本例では「true」(有効)を設定します。

⑤登録総件数を算出します。
Salesforce-Integration_vol16_image8

⑤-1 件数を格納する変数を設定ます。

  • 変数名は任意でOKです。

⑤-2 登録総件数を算出します。

  • 本例では③で結合した一覧が全体の母数になるため「priceListWithId.Rows.Count」を設定します。

⑥25件ごとに1回繰り返します。
Salesforce-Integration_vol16_image9

⑥-1 25件ずつ処理した場合の処理回数を、総件数から求めて設定します。

  • 本例では「Enumerable.Range(0, If(numOfRecords Mod 25 = 0, numOfRecords ¥ 25, (numOfRecords ¥ 25) + 1))」を設定します。

  • 「Enumerable.Range(開始番号、件数)」は開始番号から件数個の連番を文字配列で生成します。例:Enumerable.Range(0,5)⇒{"0","1","2","3","4"}

  • 「numOfRecords Mod 25」は25で割ったあまりを求めています。

  • 「numOfRecords ¥ 25」は25で割った商を求めています。

  • 25件ずつで区切って端数がでる場合は「(numOfRecords ¥ 25) + 1」で1回追加しています。

⑦登録データを蓄積して一括送信します。
Salesforce-Integration_vol16_image10

⑦-1 25件全てを正常に処理できた場合のみ登録確定とするか否かを設定します。

  • Trueを設定した場合、25件中1件でもエラーがあると全件の登録が取り消されます。Falseを設定した場合、エラーの直前までの登録が確定します。

  • 本例では「True」を設定します。

⑦-2 Salesforceステータスを設定します。

  • 必要に応じて設定します。本例では設定していますが、後続では使用しません。

⑦-3 25件の処理結果内訳を格納するため変数を設定します。

  • 必要に応じて設定します。本例では設定していますが、後続では使用しません。

  • 変数の型はDataTableです。

  • DataTable内の列はCommand,id,Status,Error Message,Referenceの5列になります。

    ※以下、出力例

(追加成功の場合)

Add,01u2v00000F6VAqAAN,Success,,

(追加失敗の場合)

Add,,Fail,JSON_PARSER_ERROR,

(全てまたはなしが「False」で一部レコードがエラーの場合)

Add,,Fail,JSON_PARSER_ERROR, Add,01u2v00000F6VBFAA3,Success,,

ここまで「25件」というキーワードを不思議に感じられた方もいるかもしれません。この25という数字は「要求を複合」Activityが1度にまとめられる命令の最大件数に由来するものです。26件目以降は実行するとエラーになってしまいます。また、まとめられる処理の種類は「レコードを挿入」「レコードを更新」「レコードを削除」のみとなっています。

本例では「レコードを挿入」のみ使用していますが、更新や削除も組み合わせ可能です。

利用にあたっては次のようなことに注意を払う必要があります。

  • 「要求を複合」の中で、挿入したレコードに対する更新はできません。これは「レコードを挿入」が実行された時点ではSalesforceにレコードが追加されておらず(要求を複合が処理するまで送信されておらず)、更新対象レコードのIDが取得できないためです。

  • 同様に、価格表と価格表エントリのように親子関係がある場合も同時に登録できません。価格表のレコードIDが得られない状態では価格表エントリの項目が未確定となってしまうためです。

  • 上記以外でもSalesforce内に、レコードの登録順序関係を制約するような処理や、レコード間の相関チェックが組み込まれている場合は登録できないことがあるので、注意が必要です。例えば、商談フェーズが見積に更新されると見積レコードが自動生成される処理が組み込まれている場合、商談フェーズの更新と見積状況の更新は同時には行えないといった具合です。

⑧25件分の価格登録命令を編集します。
Salesforce-Integration_vol16_image11

⑧-1 各回の対象レコードの開始行番号と件数を設定します。

  • 端数を考慮した回数を設定する必要があります。本例では「Enumerable.Range(25 * cnt, If(25 * (cnt + 1) <= numOfRecords, 25, numOfRecords Mod 25))」を設定します。

    ※端数のイメージは下図参照。

  • 「25 * cnt」はDataTable上の開始行番号を求めています。例:0→25→50

  • 「if(・・・)」は各回における開始番号以降の件数を求めています。25件ずつの処理のため25が基本ですが、最終回は端数を考慮する必要があるため「If(25 * (cnt + 1) <= numOfRecords, 25, numOfRecords Mod 25)」としています。

    Salesforce-Integration_vol16_image12

⑨1件分の価格情報を編集します
Salesforce-Integration_vol16_image13

⑨-1 登録対象オブジェクト「ProductEntry」を選択します。

⑨-2 登録対象の項目を選択する子ウインドウを開き、次の項目を選択します。

Pricebook2Id(価格表ID),Product2Id(商品ID),UnitPrice(リスト価格),IsActivte(有効)

⑨-3 各項目に登録する値を設定します。

  • Pricebook2Id(価格表ID)は価格表のIDを設定します。本例では④で新規登録した「sfdcPricebookId」を設定します。

  • Product2Id(商品ID)は価格表の登録する商品のIDを設定します。本例では⑧で決めたレコードの「priceListWithId(idx)("Id").ToString()」を設定します。

  • UnitPrice(リスト価格)は商品の価格を設定します。本例では⑧で決めたレコードの「priceListWithId(idx)("販売価格").ToString()」を設定します。

  • IsActive(有効)は価格表に登録した価格を有効とするか否かを設定します。本例では「true」(有効)を設定します。

これで完成です。ワークフローを実行してみてください。価格表に価格元情報が登録されていれば成功です。

まとめ

今回は行動とAPI呼び出し回数を節約するワークフローをお届しました。皆様のワークフロー開発の一助になれば幸いです。最後に今回の記事の中で取り上げた部品のリンク先などをお知らせします。

Activityの公開先 (UiPathマーケットプレイス):

https://marketplace.uipath.com/ja/listings/salesforce-activity-pack

Salesforce連携ソリューションご案内:

https://www.uipath.com/ja/solutions/technology/salesforce-automation

その他連携ソリューションご案内:

https://www.uipath.com/ja/solutions/application-cooperation-solutions

次回は「Bulkによる一括更新&取得」をおこなうワークフローをお届けします。お楽しみに。

※SalesforceはSalesforce.com,Incの商標であり、許可のもとで使用しています。

 また、UiPathでは、本記事で解説した内容に加えて、CRM/SFAの定着化のためのRPA活用について、実際の事例や、UiPathの連携ソリューションについてご紹介するeBookを無料で公開しています。eBookは下記よりダウンロードください。

Salesforce-Integration_vol22_image32

詳しくはこちら

Topics:

Salesforce
Avatar Placeholder Big
Hidetaka Obata

Senior Sales Engineer, UiPath