non-programmers salesforce 小ネタブログ

Apexやvisualforceなどプログラミングの力を使わずにどこまでやれるか小ネタを投稿します。

コミュニティユーザがDataloaderを使う方法

コミュニティユーザにDataloaderを使わせたく、調べました。

マニュアルに書いてあるのですが、ここをピンポイントで説明したものがなかったので以下引用します。

https://resources.docs.salesforce.com/208/latest/ja-jp/sfdc/pdf/data_loader_impl.pdf

 

  • データローダバージョン 36.0 以降では、Salesforce Communities がサポートされています。Communities ユーザ は常にデータローダの OAuth オプションを指定してログインします。Communities OAuth を有効にするに は、ユーザが config.properties ファイルを次のように変更します。

    • –  次の行の太字部分をコミュニティのログイン URL に変更します。行の最後にスラッシュ (/) を追加しない でください。

      sfdc.oauth.Production.server=https\://login.salesforce.com 以下に例を示します。

    • –  次の行の太字部分をコミュニティのホスト名に変更します。 sfdc.oauth.Production.redirecturi=https\://login.salesforce.com/services/oauth2/success

      以下に例を示します。

      config.properties ファイルは、conf デフォルト設定ディレクトリにあり、次の場所にインストールさ れています。

    • –  MacOS: /Applications/Data\ Loader.app/Contents/Resources/conf/

    • –  Windows: 現在のユーザの場合は %LOCALAPPDATA%\salesforce.com\Data Loader\samples\conf\

      すべてのユーザの場合は C:\ProgramData\salesforce.com\Data Loader\samples\conf\

 

 

前提条件としてプロファイルで「APIを利用」にチェックが入っていることが必要です。

 

Dataloaderの設定ですがMacの場合、ApplicationのDataloaderファイルでパッケージの内容を表示をクリックします。

f:id:non-prog-sf:20160406161417p:plain

ここのResource→conf→config.properityというファイルをテキストエディタなどで開きます。

f:id:non-prog-sf:20160406161441p:plain

下の図の38、39行目にあるhttps〜をコミュニティのURLに変えれば良いんですね。

f:id:non-prog-sf:20170828193118p:plain

 

ちゃんとコミュニティユーザの閲覧範囲どおりにしかレコードの作成や閲覧はできないので、制限をかけている限りは勝手に全データを書き換えるなんてことはできません。

フローの高速作成を使ってレコードの一括作成を行う【Salesforce】

初めてVisualWork Flowの高速作成を使ったので、使い方をまとめました。

 

まず目的から。

都市マスタというオブジェクトに市町村名と金額が1〜3まであります。今回の都市マスタには北海道179市町村(つまり179レコード)が入っています。

一方、指示書にはテキスト1〜3があって、その下に多対多の関係になるように実行書があります。

指示書を作ると、指示書と都市マスタそれぞれの情報を持った実行書が作られるようにしたいというのが今回の目的です。

f:id:non-prog-sf:20161013130020p:plain

 

都市マスタはこんな感じ。

f:id:non-prog-sf:20161013130152p:plain

 

手順ですが、最初にフローを作ります。

f:id:non-prog-sf:20161013130305p:plain

 

スタートは高速検索から。

都市マスタのデータを一括で引っ張ってきましょう。

f:id:non-prog-sf:20161013130401p:plain

 

高速検索で使うSオブジェクトコレクション変数は都市マスタを参照するように作ります。

f:id:non-prog-sf:20161013130512p:plain

 次にループです。ループ対象は先ほど作ったSオブジェクトコレクション変数です。ループ変数はSオブジェクト変数を新規作成します。

f:id:non-prog-sf:20161013141856p:plain

 

ループ変数に使うSオブジェクト変数は、ループ対象のSオブジェクトコレクション変数と同じオブジェクトを見に行くように作ります。

f:id:non-prog-sf:20161013143404p:plain

 

次に割り当てですが、その前に一つポイントがあって、今回作成するオブジェクトに関するSオブジェクト変数を作成しておきます。

f:id:non-prog-sf:20161013160137p:plain

 

 割り当ての画面です。変数の方に先ほど作ったSオブジェクト変数を、値の方にループのループ変数として割り当てたSオブジェクト変数を当てます。

f:id:non-prog-sf:20161013170601p:plain

 

Sオブジェクト変数への値の割り当て方ですが、オブジェクト変数からドリルダウンすることができます。そして値を入れたい項目を選びます。値の方も同じです。

f:id:non-prog-sf:20161013170809p:plain

 

あと新規作成で、今回のように他オブジェクトとリレーションを行う場合にはそれを忘れないようにする必要があります。都市マスタと実行書の関係のようにレコードごとに異なるレコードとリレーションを作る場合は値はSオブジェクト変数でIDを選びます。

f:id:non-prog-sf:20161013172129p:plain

 指示書と実行書のように一つのレコードと紐付く場合は変数で大丈夫です。変数を作る際には入力のみにして、プロセスビルダーで値を与えられるようにしておいてください。

f:id:non-prog-sf:20161013172545p:plain

 

 

そして高速作成をやる場合はもう一つ割り当てを作ります。変数側には新しくSオブジェクトコレクション変数を入れます。値には先ほどの割り当てで変数として使ったSオブジェクト変数を入れます。

f:id:non-prog-sf:20161013171015p:plain

 

新しく作るSオブジェクトコレクション変数は作成するオブジェクトを選びます。

f:id:non-prog-sf:20161013171358p:plain

 

最後に高速作成です。割り当ての変数は割り当て2回目で作ったSオブジェクトコレクション変数です。

f:id:non-prog-sf:20161013171537p:plain

 

あとはリレーションを作っていってください。高速検索を開始に指定して、フローの有効化も行っておいてください。

f:id:non-prog-sf:20161013130305p:plain

 

あとはプロセスビルダーです。プロセスビルダーで今回作ったフローを実行するように設定してください。フロー変数への値割り当てを忘れずに。

f:id:non-prog-sf:20161013172743p:plain

 

さて、実行してみます。こんな指示書を作ってみます。

f:id:non-prog-sf:20161013172956p:plain

保存すると、実行書が作られていることがわかります。金額の値は各都市マスタの情報を引っ張ってきています。

f:id:non-prog-sf:20161013173402p:plain

 

レポートを作ってレコードがきちんと作られているか確認しましたがちゃんと北海道の市区町村分の179レコードありました。

f:id:non-prog-sf:20161013173819p:plain

リストビューで一括削除するボタンをほぼノンプログラミングで作る【Salesforce】

リストビューで一括更新するボタンの応用編です。

non-prog-sf.hatenablog.com

 

こちらもvisualwork flowで作ってみます。今回は細かい端折るので、詳しいことは前回のものを参考にしてください。また、ケースオブジェクトにて行います。

まずフローの完成イメージです。

f:id:non-prog-sf:20161004175633p:plain

ループは前回と同じです。ループ対象にSオブジェクトコレクション変数、ループ変数にSオブジェクト変数を設定します。

f:id:non-prog-sf:20160928170026p:plain

 

Sオブジェクトコレクション変数は入力/出力種別を入力のみにて設定してください。

f:id:non-prog-sf:20160928170104p:plain

Sオブジェクト変数は非公開で大丈夫です。

f:id:non-prog-sf:20161004163119p:plain

割り当ては変数にSオブジェクトコレクション変数を新規作成したもので設定します。値はSオブジェクト変数です。

f:id:non-prog-sf:20161004180311p:plain

Sオブジェクトコレクション変数は非公開で大丈夫です。

f:id:non-prog-sf:20161004164614p:plain

 

高速削除の設定をします。変数には割り当てで使ったSオブジェクトコレクション変数を当ててください。

f:id:non-prog-sf:20161004180607p:plain

 

フローをつなげます。ループと割り当ては双方向で繋いで、ループの終了を高速削除につなぎます。

f:id:non-prog-sf:20161004175633p:plain

 

次にVisualforceです。

-----------------------------------

<apex:page standardController="Case" recordSetVar="Cases"> 
<flow:interview name="ListDeleteCase"
finishLocation="{!URLFOR('/500?')}">
<apex:param name="SOCCase1" value="{!Selected}"/>
</flow:interview>
</apex:page>

-----------------------------------

 

順に説明します。

standardController="Case"

ここの赤字は対象のオブジェクトを設定します。

 recordSetVar="Cases"

というrecordSetVarというところがあるのですが、

ここは何か任意の文字列を入れていればいいようです。

 

<flow:interview name="ListDeleteCase"
finishLocation="{!URLFOR('/500?')}">

紫色のところにフロー名を、水色のところに完了後にランディングさせたいページリンクを入れます。通常、元のリストビューに戻って欲しいので、リストビューのURLを入れると思います。

 

<apex:param name="SOCCase1" value="{!Selected}"/>

緑色にフローの変数を、茶色のvalueに値を入れます。フロー作成時にSオブジェクトコレクション変数を入力のみに設定しましたが、これには{!Selected}を割り当てます。これはリストビューでチェックされたレコードのIDを持ってきてくれるようです。

 

次にカスタムボタンの設定です。

該当オブジェクトのボタン、リンク、及びアクションで新規ボタンまたはリンクをクリックします。表示の種類をリストボタンにして、チェックボックスの表示にもチェックを入れます。動作は「現在のウィンドウにサイドバー及びヘッダーなしで表示」を選び、内容のソースはVisualforceページにして、先ほど作ったVisualforceページを選択します。

f:id:non-prog-sf:20161004180921p:plain

 

次で最後です。検索レイアウトからボタンをリストビューに表示させます。検索レイアウトを開いて、リストビューで編集を押します。

f:id:non-prog-sf:20161004172804p:plain

カスタムボタン欄に先ほど作ったものがあるので、それを選択します。以上で完了です。

f:id:non-prog-sf:20161004181021p:plain

半分ぐらい前のコピペでしたね。

 

テストです。チェックボックスにチェックを入れて、一括削除ボタンを押します。

f:id:non-prog-sf:20161004181127p:plain

 

無事削除されました。

f:id:non-prog-sf:20161004181223p:plain

リストビューで一括更新するボタンをほぼノンプログラミングで作る【Salesforce】

リストビューにカスタムボタンを追加して、チェックボックスを付けたレコードの一括更新をしたいという要望に対応しました。

 

これまでこのような課題に対応するにはjavascriptでのコーディングが必要と考えられてきました。

dackdive.hateblo.jp

リストビュー内カスタムボタンによるレコードの一括更新

https://developer.salesforce.com/forums/?id=906F0000000D7JPIA0

 

これをVisualWork Flowでどうにか実現したい!ということで色々頭をひねった結果が次のとおりです。

 

今回はケースにある3項目をボタン一つでまとめて更新します。

f:id:non-prog-sf:20160928165958p:plain

 

まずループを設定します。いつものことですが、ループ対象はSオブジェクトコレクション変数、ループ変数はSオブジェクト変数です。

f:id:non-prog-sf:20160928170026p:plain

ループ対象にはSオブジェクトコレクション変数を設定します。入力/出力種別は入力のみに設定します。

f:id:non-prog-sf:20160928170104p:plain

 

Sオブジェクト変数も合わせて設定します。こちらは非公開で大丈夫です。

f:id:non-prog-sf:20161004163119p:plain

 

ループの次は割り当てです。変数の設定がポイントです。

f:id:non-prog-sf:20161004163232p:plain

変数は先ほど作成したSオブジェクト変数から変更させたい項目を選ぶのです。今回の場合このあと高速更新を行うのですが、このときにはSオブジェクト変数で該当の項目に値を割り当てます。

f:id:non-prog-sf:20161004163449p:plain

また、先ほどの割り当てですが、変数を指定して、外部の値を取り込むことも可能です(上記の画像であれば{!User})。

 

割り当ての次にもう一つ割り当てを設定します。割り当て2と仮に呼びます。ここで変数には新しくSオブジェクトコレクション変数を作ります。値には既に作成したSオブジェクト変数を設定します。

f:id:non-prog-sf:20161004163839p:plain

 

作成するSオブジェクトコレクション変数は非公開のもので大丈夫です。

f:id:non-prog-sf:20161004164614p:plain

 

次に高速更新を設定します。変数には割り当て2で新規作成したSオブジェクトコレクション変数を設定します。

f:id:non-prog-sf:20161004164725p:plain

 

以上、作ったものをつないでいきます。ループをスタートとしてループ→割り当て1→割り当て2→ループとして、ループの終了を高速更新につなげます。これでフローは完成です。

f:id:non-prog-sf:20160928165958p:plain

 

次にVisualforceの設定をします。

こんなコードです。

-----------------------------------

<apex:page standardController="Case" recordSetVar="Cases">
<flow:interview name="ListUpdateCase"
finishLocation="{!URLFOR('/500?')}">
<apex:param name="SOCCase1" value="{!Selected}"/>
<apex:param name="User" value="{!$User.Id}"/>
</flow:interview>
</apex:page>

-----------------------------------

 

順に説明します。

standardController="Case"

ここの赤字は対象のオブジェクトを設定します。

 recordSetVar="Cases"

というrecordSetVarというところがあるのですが、

ここは何か任意の文字列を入れていればいいようです。

 

<flow:interview name="ListUpdateCase"
finishLocation="{!URLFOR('/500?')}">

紫色のところにフロー名を、水色のところに完了後にランディングさせたいページリンクを入れます。通常、元のリストビューに戻って欲しいので、リストビューのURLを入れると思います。

 

<apex:param name="SOCCase1" value="{!Selected}"/>
<apex:param name="User" value="{!$User.Id}"/>

緑色にフローの変数を、茶色のvalueに値を入れます。フロー作成時にSオブジェクトコレクション変数を入力のみに設定しましたが、これには{!Selected}を割り当てます。これはリストビューでチェックされたレコードのIDを持ってきてくれるようです。

また、操作ユーザのIDは{!$User.Id}で持ってきます。

 

これでVisualforceは完了です。

 

次にカスタムボタンの設定です。

該当オブジェクトのボタン、リンク、及びアクションで新規ボタンまたはリンクをクリックします。表示の種類をリストボタンにして、チェックボックスの表示にもチェックを入れます。動作は「現在のウィンドウにサイドバー及びヘッダーなしで表示」を選び、内容のソースはVisualforceページにして、先ほど作ったVisualforceページを選択します。

f:id:non-prog-sf:20161004172327p:plain

 

次で最後です。検索レイアウトからボタンをリストビューに表示させます。検索レイアウトを開いて、リストビューで編集を押します。

f:id:non-prog-sf:20161004172804p:plain

カスタムボタン欄に先ほど作ったものがあるので、それを選択します。以上で完了です。

f:id:non-prog-sf:20161004172906p:plain

動作確認です。リストビューでレコードを選び、ボタンを押してみます。

f:id:non-prog-sf:20161004173138p:plain

無事更新されました。

f:id:non-prog-sf:20161004173211p:plain

 

削除版も作りました。

non-prog-sf.hatenablog.com

 

ユーザ登録後に自動的に公開グループに登録する方法【salesforce】

もともとの始まりはパートナーコミュニティにおいて、ユーザ管理権限を持たないユーザがパートナーアカウントの登録を行った際に、自動的にグループに登録して欲しい、という要望を実現するために作ったものです。

ユーザ登録後に手動で公開グループへ登録するのは手間ですし、忘れてしまいがちな行動なので、できるなら自動化したいものです。

 

今回はあらかじめ作っておいたグループ名とユーザの部署が同一だった場合に、そのグループへユーザを自動的に追加する想定で作ってみました。

f:id:non-prog-sf:20160901123520p:plain

 

これもフローとプロセスビルダーで解決します。

まずレコードの検索を行います。今回は部署名でグループ名を検索しますので、Nameに対して、部署名が入る変数(DepartmentName)と一致させます。

更にここが重要ですが、TypeでRegularを選びまず。Regularが公開グループのことで、これを選ばないと同一のキューがあった場合にそっちに紐付いてしまう可能性があります。公開グループもキューもどちらもGroupなのです。

f:id:non-prog-sf:20160901123816p:plain

DepartmentNameの変数はテキスト型、入力のみです。

f:id:non-prog-sf:20160901124232p:plain

 

 

「レコードの項目に変数を割り当ててフローで参照します。」では、IdをGroupIdとして格納します。一応レコードが検出されない場合、Null値を変数に割り当てます。にチェックを入れてください。次の判定で使います。

f:id:non-prog-sf:20160901124138p:plain

 

GroupIdの変数はテキスト型、非公開です。

f:id:non-prog-sf:20160901124309p:plain

 

次にGroupがあったかどうかを判定させます。GroupIdが見つかった(Nullではない)場合、次のステップに進めるようにします。Nullの場合はここで終了です。

f:id:non-prog-sf:20160901130114p:plain

 

次にレコードの作成を作ります。対象のオブジェクトは「GroupMember」です。GroupIdは先程の変数GroupIdを、UserOrGroupIdはユーザIDを格納する変数UserIdを割り当てます。

f:id:non-prog-sf:20160901124445p:plain

UserIdはテキスト型、入力のみです。

f:id:non-prog-sf:20160901124557p:plain

 

あとはつないで、レコードの検索を開始要素として設定します。

f:id:non-prog-sf:20160901130221p:plain

 

次にプロセスビルダーです。

アクショングループの条件は部署がヌルでないこと(False)で設定します。安易ですが。

f:id:non-prog-sf:20160901144458p:plain

 

そしてルール適用時のアクションとして先ほど作ったフローを起動します。それぞれの変数にはユーザの部署やIDを付与してください。

最後にプロセスビルダーを有効化すると完成します。

f:id:non-prog-sf:20160901144601p:plain

 

非常にシンプルではあるのですが、これだけで自動的にグループに追加されるようになります。もちろんメンテナンス(削除や変更など)を追加すると手順はかなり変わるのですが、この方法でユーザにユーザ編集権がなかったとしてもグループへの追加が可能になります。

【salesforce】レコード削除時に「アクセス権がありません」を回避して削除できるようにする設定

先日レコードを削除しようとした時にエラーが発生しました。

f:id:non-prog-sf:20160818181956p:plain

これはロールが原因でした。

レコードを削除しようとする時に「アクセス権がありません」のエラーになる理由

例え共有ルールで参照・更新権限を付与されていたとしても、ロール階層で下位のユーザーが上位のユーザーの所有するレコードを削除することはできません。 

知らなかったです。

 

今回はこの問題を解決する方法をフローを使って組みました。今回は商談を削除する場合を例にしています。

まず、このようなフローを作ります。

f:id:non-prog-sf:20160818182149p:plain

手順を説明します。まずレコードの更新で所有者を削除する人に置き換えます。

f:id:non-prog-sf:20160818182213p:plain

 

変数はテキスト形式で商談IDやユーザIDを保管できるように作っておきます。どちらも種別は入力のみです。

f:id:non-prog-sf:20160818182415p:plain

f:id:non-prog-sf:20160818182420p:plain

次にレコードの削除を設定します。所有者を置き換えた商談レコードを削除します。

f:id:non-prog-sf:20160818182501p:plain

 

あとはレコードの更新を開始に設定して、更新→削除の順でつなげます。あとは保存して名前をつけてください。有効化も忘れないようにしてください。

f:id:non-prog-sf:20160818182149p:plain

次にvisualforceの設定をします。

visualforceは従来プログラミングですが、値の置き換えだけでどうにかできるのでそんなに難しくありません。

visualforceは開発→visualforceページにて新規作成します。

f:id:non-prog-sf:20160818183620p:plain

 

以下元となるコードを貼ります。

<apex:page standardController="Opportunity">
<flow:interview name="delete_opportunity"
finishLocation="/{!Opportunity.AccountId}">
<apex:param name="OwnerId" value="{!$User.Id}"/>
<apex:param name="OpportunityId" value="{!Opportunity.Id}"/> </flow:interview> </apex:page>

f:id:non-prog-sf:20160818183728p:plain

 

以下1つずつ説明します。基本的に色のついた部分を差し替えるだけです。

 

<apex:page standardController="Opportunity">

どのオブジェクトに対して動作させるか、という行です。ここでは商談なのでOpportunityを選びます。カスタムオブジェクトももちろん大丈夫です。その時には__cを付けるのを忘れずに。

<flow:interview name="delete_opportunity"

どのフローを起動させるかです。先ほど保存したフローの名前を紫色の部分に設定してください。

finishLocation="/{!Opportunity.AccountId}">

終わった時にどこにランディングさせるかです。今回は商談データの削除なのでリレーションがある取引先に飛ばすように設定しました。

ここで出てくる{!〜〜〜〜}ですが、カスタムリンクの設定時に出てくる差し込み項目と同じ形式になります。カスタムリンクの画面を同時に開いて、差し込み項目を持ってくるようにするといいと思います。

f:id:non-prog-sf:20160818184941p:plain

<apex:param name="OwnerId" value="{!$User.Id}"/> 
<apex:param name="OpportunityId" value="{!Opportunity.Id}"/>

これはフローの変数(緑色)に対して、入れたい値の参照先(オレンジ色)を設定します。先ほどの差し込み項目で項目を持ってきます。OwnerIdには{!$User.Id}とこのフローを起動する(削除ボタンを押す)ユーザIDを持ってくるように設定します。OpportunityIdには{!Opportunity.Id}と商談IDを設定します。

 

Visualforceの設定は以上です。

次に削除ボタンに対して、このvisualforceを呼び出す設定を行います。

削除したいオブジェクトのボタン、リンク、およびアクションをクリックして、削除の編集をクリックします。

f:id:non-prog-sf:20160826123432p:plain

f:id:non-prog-sf:20160826123441p:plain

上書き手段で先ほど作ったVisualforceページを呼び出します。これを保存すると完成です。

f:id:non-prog-sf:20160826123454p:plain

なお、重要なことですが、ユーザプロファイルなどでフローの実行を有効化しておいてください。

f:id:non-prog-sf:20160826123839p:plain

これをやらないと、以下のようなエラーが出ます。私はここでつまづきました。

f:id:non-prog-sf:20160826123727p:plain

 

手順としてはそこまで複雑ではないかと思います。visualforceのことはよくわかりませんが、フローの呼び出しとして活用する方法を覚えていけば、設定の幅が広がりそうです。

Mac版Dataloader 36.0以降(Spring'16以降)での文字化け(UTF-8)を解決する方法

Spring'16でDataloaderが新しくなりました。

https://releasenotes.docs.salesforce.com/ja-jp/spring16/release-notes/rn_forcecom_data_data_loader.htm

 

それにともなってMac版のDataloaderでなぜか文字化けする現象が。具体的にはUTF-8で入出力されるようになってしまいました。つまりEXCELでエクスポートしたファイルを開いたり、インポートやアップデートしようとすると日本語がぐちゃぐちゃになってしまうのです。

 

そうこうしているうちにサポートがでました。

Mac向けデータローダ Ver. 36 以降にて CSVファイルをSJISにて作る方法

https://help.salesforce.com/apex/HTViewSolution?urlname=000233329&language=ja

右クリックして「パッケージの内容を表示」をクリック

f:id:non-prog-sf:20160406161417p:plain

 

Contents→info.plistをテキストエディタで開く。

f:id:non-prog-sf:20160406161441p:plain

ページ下部の</array>の上に

<string>-Dfile.encoding=SJIS</string>

を挿入(結構下にあります)

f:id:non-prog-sf:20160406161621p:plain

 

一応これでOKです。あとはMacを再起動すれば使えます。

ただし、このコードを間違えると(空白を入れてしまうとか)dataloaderが動かなくなってしまうのでご注意を。

f:id:non-prog-sf:20160406163546p:plain