[Salesforce] 単一の CSV ファイルから、取引先/取引先責任者/商談/商品に分割してインポートする
お久しぶりです、サポートデスクの “GT” です。
そういえば私も「ノンコーディング・デベロッパー」でしたね(笑)。
弊社サポートでは、お客様に Salesforce の基本的なオペレーションに関する個人~少人数対象のトレーニングを行っておりまして、お客様の理解度に合わせてきめ細かくカスタマイズされたカリキュラムがお蔭様でご好評をいただいております。
その中で、先週から今週に掛けて実施した「データローダ概要:基本編&応用編」に基づいて、実際のお客様の運用に即し「データの効率的なインポート」をレクチャーしたその内容が、これは一人でも多くの人と共有すべきだと思い、Deferloader ブログで書かせていただきます。
教育関係(主に企業向けセミナーの開催)に従事されているお客様の要件、それは、
「今まで Lotus Notes で管理していたセミナー受付情報を、今後 Salesforce で一元管理できるように、今までの履歴を移行したい」
というもので、「それをデータローダでどのようにやるのかを学習する」ために、弊社オフィスに三回お見えになられました。
お客様が今まで Lotus Notes で管理していた「セミナー受付履歴」は、このようなシートでした。
(もちろん実際のシートではなく、私がそのシートをイメージして作った架空の受付履歴情報です。)
[セミナーID] はセミナーに振られる ID で、[セミナー受付ID] は「特定のセミナーに特定の受講者が申し込んだ」ことに対して振られるIDです。
それ以外の項目、例えば会社や受講者に対しては、一意の通し番号は振られていません。
このシートを Salesforce に取り込むわけですが、もちろん今後のことを考えると、「カスタムオブジェクト一つだけ作ってそこに全部流し込む」では全く発展性が無く、しかるべきデータをしかるべきオブジェクトに、そして、出来ることなら「取引先」や「商談」といった Sales Cloud の標準オブジェクトを使用して取り込んだ方が、今後のメンテナンスやデータ活用(レポートやダッシュボードでの集計)の際に利点があります。
なので、上記シートのどの項目をどのテーブルに割り振るかを整理することが、事前準備として非常に重要なわけです。
今回は以下のように各項目を Sales Cloud 標準オブジェクトに割り振ってみました。
取引先:[会社名]
取引先責任者:[受講者:姓] [受講者:名] [役割]
商談:[セミナー受付ID] [開催日] [状況]
商品:[セミナーID] [セミナー名] [受講料]
セミナーの開催予定/履歴は商品マスタで管理し、受講者マスタ(取引先責任者)のセミナー申込は商談で管理するという「基本に忠実な」スタイルを取ります。
Sales Cloud オブジェクトのリレーション構造を今一度振り返ってみましょう。
薄字で表記したオブジェクト(商談商品、取引先責任者の役割、価格表エントリ)は、独立したタブを持たない、いわゆる「連結オブジェクト」です。
今回のインポートを行うにあたり、これらのオブジェクトにどのように値を流し込むかが、成功の鍵を握っています。
データを取り込む順番は以下の通りです。
「メモ」に書いてある内容は順を追って説明します。
さて。
一番の厄介な問題が、複数のオブジェクトにデータを流し込んだ際に、どのようにしてリレーションを維持するかという点です。
リレーションを維持するには、各レコードに「他レコードと重複の無い一意のID」が振られている必要があります。
一意のID項目の Salesforce への取り込みは、「外部ID」項目でハンドリングします。
「外部ID」項目には、通常は外部DBで自動生成された通し番号を使用しますが、ご覧の通り今回のデータには存在しません。
会社情報を [取引先] オブジェクトに取り込む際、他の会社と重複の無いユニークな情報を持たせるために、{A0001} {A0002} のような番号を振る方法もありますが、会社名の重複が一切無い(=「同名別会社」が存在しない)場合は、会社名自体を「外部ID項目の値」としてしまってもOKです。
[会社名] とは別に、会社名の列を丸ごとコピーして [会社名(外部ID用)] とします。
CSV上で作成した外部ID列の受け皿として、Salesforce 上に取引先カスタム項目「会社名(外部ID用)」を作成します。
データローダを起動して [Insert] または [Upsert] を選択します。(既存のリレーションに紐付ける必要が無いので、取引先のインポートの場合は [Insert] でもOKです。)
項目の関連付けで、Salesforce 上の外部ID項目とCSVファイルの外部ID項目列を紐付けます。
これで取引先の取り込みはできました。
次は取引先責任者を取り込みますが、同じように一意のIDを持たせる必要があります。
会社名と違って、個人名は「同姓同名」が普通に存在するため、名前をユニークな外部IDにするのは無理があります(=あっという間に値の重複エラーが発生します)。
しかし、「会社名 + 名前」の組み合わせなら、同じ会社に同姓同名の人がいるというのは余程の大きな会社でも無い限りそうそうないので、外部IDの値として使えそうです。
(「会社名 + メールアドレス」の組み合わせならほぼ重複は回避できるはずです。社内の同姓同名でもメールアドレスまで同じというのはありえないので。)
Excel で複数セルの文字列を連結するには [CONCATENATE] 関数を使用します。
これで取引先責任者にも一意のIDを振ることができました。これを「受講者ID」とします。
取引先同様に、取引先責任者もデータローダで取り込みます。
取引先の外部ID項目と関連付ける必要があるため、[Insert] ではなく [Upsert] で取り込みます。
引き続いてセミナー情報の [商品] へのインポートです。
これは簡単です、既にセミナーIDが振ってありますから。
関連付けるリレーションも無いので、[Insert] でOKです。
さてさて、次の関門です。
商品テーブルにセミナー情報をインポートしても、そのままでは商談に紐付けることができません。
商談と商品を紐付けるには、
1.商品を価格表に登録する(=価格表情報と商品情報を [価格表エントリ] テーブルに登録する)
2.価格表に登録した商品と商談の情報を [商談商品] テーブルに登録する
という二段階の作業が必要です。
今回は「セミナーの価格は誰が受けても同額」なため、複数の価格表を用意する必要がありません。
セミナーの価格は全部「標準価格表」に登録します。
標準価格表に登録するには、標準価格表の一意の情報、つまり「Salesforce ID」が必要となります。
価格表を一切登録していない初期状態では、[価格表] テーブルには標準価格表の情報のみが存在するため、データローダから全件エクスポートを行えば、標準価格表の Salesforce ID を抜き出すことができます。
エクスポートを実行することで、標準価格表のIDが “01s10000000r7kiAAA” であることが確認できました。
商品と価格表の情報を [価格表エントリ] テーブルに登録しますが、実は Summer’14 のリリースで素晴らしい機能改善がありまして、これは声を大にして「ありがとう SFDC !」と言っておかなければいけないほどのインパクトです。
Salesforce.com Summer ’14
リリースノート – カスタマイズ可能な価格表エントリ
http://docs.releasenotes.salesforce.com/ja-jp/api/release-notes/rn_sales_pb_entry.htm
その改善内容とは、「外部ID項目を価格表エントリ上に作成可能」になったという点です。
価格表エントリに外部IDを使えないと、「商品と価格表の情報を価格表エントリに Insert」⇒「価格表エントリを全件 Export」⇒「商品の外部IDと価格表エントリの Salesforce ID を Excel 上で VLOOKUP を使って再紐付け」⇒「商談マスタの商品IDも VLOOKUP で置き換え」⇒「その上で商談商品の Insert」という、実に気が遠くなる作業が必要となり、外部ID項目が実装可能になったことでこの辺の面倒くさい作業から開放されたのは、ものすごく「朗報」だと思います。
価格表エントリ用のCSVファイルは、次のようなデータ構成となります。
価格表を複数用意する必要が無い場合は、価格表エントリの外部ID項目に投入する「セミナー価格ID」の値は、セミナーIDのコピーでOKです。
あと、「有効フラグ(ISACTIVE)」の列を追加して、値を “TRUE” にします。このフラグはどうやら必須のようです。
データローダで価格表エントリをインポートします。商品で外部IDを使用する関係上(セミナーID)、[Upsert] を使用します。
「価格表エントリ」は隠しオブジェクトのため、オブジェクト選択の際 “Show all Salesforce objects” チェックをオンにします。
項目の紐付けは以下のようになります。
価格表エントリの Upsert が無事済んだら・・・
そういえば商談のインポートが未だでした。
商談の新規作成時に必須項目となるのは [商談名] [完了予定日] [フェーズ] です。
[完了予定日] にはセミナー開催日を、[フェーズ] には申込/受講状況を当てはめます。
セミナー受付IDを商談の外部IDとします。(最初からIDが振ってあるのを見ると心が安らぎます・・・)
余談ですが、[フェーズ] に状況値を当てはめる場合、カスタム選択肢を予め追加しておく必要があります。
ここで手を抜くと、状況値の取り込みはできるのですが、後で売上予測計算ができなくなります。
商談のインポートも、会社名(外部ID)と関連付けをする関係から、[Upsert] である必要があります。
項目の紐付けは以下の通りです。
商談のインポートが正常に完了したら、次はいよいよ、商談と商品(価格表エントリ)の情報をまとめて [商談商品] テーブルにインポートします。
まるで「両側から掘り進めたトンネルが開通する瞬間」のような感慨があります。
[商談商品] の必須項目は、商談情報、商品情報、価格、あと「数量」です。
とはいえ、登録する商談は「一個人が単一のセミナーを受講する」なので、数量は全部「1」を振ればOKです。
商談情報は「セミナー受付ID」、商品情報は「セミナーID」、いずれも外部ID項目で紐付けます。
外部ID項目で紐付けを行う関係から、インポート作業は当然 [Upsert] で行います。
[商談商品] も [価格表エントリ] 同様に “Show all Salesforce objects” チェックをオンにすることで選択可能になります。
項目の紐付けは以下の通りです。
商談商品のインポートが正常に完了することで、商談情報に商品(セミナー情報)のエントリが表示されるようになりました。
いよいよ最後の作業です。商談と会社の紐付けはできましたが、肝心の「誰がセミナーを受けたか」の情報がまだ紐づいていません。
最初に載せたリレーション図を今一度振り返っていただきたいのですが、商談と取引先責任者の間には直接のリレーションは無く、間に「取引先責任者の役割」という隠しオブジェクトを介してリレーションしています。
(一人の取引先責任者は複数の商談に関与し、一つの商談には複数の取引先責任者が関与するという「リレーションの性質」に基づいています。)
仕上げとして、[取引先責任者の役割] テーブルに、取引先責任者と商談の情報を投入して、商談と取引先責任者を紐付けます。
[取引先責任者の役割] のインポートで必要な情報は、商談情報(セミナーID)、取引先責任者情報(受講者ID)、 商談に対する取引先責任者の役割の3つです。
セミナーIDはオリジナルのシートに最初から存在しています。
受講者IDは「会社名 + 受講者の姓名」を連結したものを外部ID化していました。
「役割」は、元々のシートにあった「受講者」「請求担当者」などの種別を記載した列を当てはめます。
データローダでのインポート操作は、言うまでも無く [Upsert] を使用します。
隠しオブジェクトなので “Show all Salesforce objects” チェックをオンにしますが、注意が必要なのは、「取引先責任者の役割」が二つあるという点です。
商談に対する取引先責任者の役割の場合は、”OpportunityContactRole” の方を選びます。
項目の紐付けは以下のようになります。
(関係ない項目はCSVの保存直前に列削除をしてしまってもいいかと思います)
*******************************
取引先責任者の役割のインポートが終わりました。
さあ、何かひとつ商談を開いてみましょう。
感動の瞬間です。
おお、あの一枚のCSVシートから、きちんと然るべきオブジェクトに整理されてデータが投入されている!!
データローダの特質、というよりも Sales Cloud のリレーション構造を熟知すれば、Lotus Notes から Salesforce へのデータ移行も決して難しいものではありません。
でもやっぱり、「予めオリジナルデータできちんと一意の項目値を管理しておく」に越したことはないですよね・・・。
*******************************
【宣伝ターイム!!!】
弊社カスタマーサービス室では、「トレーニング体験キャンペーン」を実施中です。
Salesforce 認定アドミニストレータ/デベロッパー資格を有したコンサルタントが、お客様のニーズに合わせたきめ細かいカリキュラムにて、Salesforce 基本操作のトレーニングを行っております。
その「お墨付きのハイクオリティなトレーニング」が、今なら初回無料で受けられます!
さあ!以下のページから今すぐお申込を!!