標準機能を使わずに開発で対応する場合、項目追加等のちょっとした改修でもいちいちソースコードを修正する必要があったり、**開発者がいなくて修正自体できない!**みたいなことが起こったりします。
ちょっと項目を追加したいだけなのに…というのをなんとかできないか考えて、項目セットを使ってみたらメンテナンスが楽にならないかなと思いました。
項目セットって?
詳細はこちら。
項目セットはオブジェクト内の項目を一つにまとめて管理してレイアウトに使ったりすることができる機能なのですが、
Salesforce自体簡単にレイアウトなどを修正できるのであまり使ったことがありませんでした。
実際使ってみるとページレイアウトの編集と同様に項目の追加・削除が簡単にできることがわかります。
これならサルでも修正できそうなので問い合わせが減りそうです。
Apexクラス内での使い方
項目セットはApexクラス内では「FieldSetクラス」から呼び出して使用します。
項目セットの中に含まれている項目はSObjectType.sObject.FieldSets.fieldSetName.getFields()
のようにすると取得できます。
戻り値は「List<Schema.FieldSetMember>」となり、各項目は「getFieldPath()」メソッドで取得することができます。
for(Schema.FieldSetMember fsm : SObjectType.sObject.FieldSets.fieldSetName.getFields()) {
system.debug('この項目は:' + fsm.getFieldPath());
}
Queryを作成する時にこれを使うと、動的に取得する項目を変更することができます。
また、レコードの項目の値はsObject.get(Schema.FieldSetMember.fieldPath)
のようにすると取得できます。
サンプル
商談に親子関係を作成し、親商談の特定の項目が更新されたら子商談の同じ項目を更新しています。
private void updateChildOpp (Opportunity[] newObjs) {
List<Id> parentIdList = new List<Id>();
// 更新対象の商談件数分繰り返す
for (Opportunity opp : newObjs) {
// 親商談に紐づく子商談を取得する
parentIdList.add(opp.Id);
}
// 子商談用のクエリ
String query = 'SELECT Id, ';
// 案件基本情報(OppDefaultInfo)の項目セットからクエリで取得する対象のAPI名を取得する
for(Schema.FieldSetMember fsm : SObjectType.Opportunity.FieldSets.OppDefaultInfo.getFields()) {
query += fsm.getFieldPath() + ', ';
}
// 親商談との比較用クエリ
String parentQuery = '';
// 案件基本情報(OppDefaultInfo)の項目セットからクエリで取得する対象のAPI名を取得する
for(Schema.FieldSetMember fsm : SObjectType.Opportunity.FieldSets.OppDefaultInfo.getFields()) {
parentQuery += 'OrgOpportunity__r.' + fsm.getFieldPath() + ', ';
}
query += parentQuery;
query += ' OrgOpportunity__c FROM Opportunity WHERE OrgOpportunity__c IN :parentIdList';
// 商談から子商談および親商談の情報を取得する
List<Opportunity> childOppList = Database.query(query);
List<Opportunity> updateList = new List<Opportunity>();
for (Opportunity opp : childOppList) {
Boolean addFlg = false;
for(Schema.FieldSetMember fsm : SObjectType.Opportunity.FieldSets.OppDefaultInfo.getFields()) {
// 子商談の項目セットの値を親商談の値が違う場合はセットする
if (opp.get(fsm.fieldPath) != opp.OrgOpportunity__r.get(fsm.fieldPath)) {
opp.put(fsm.fieldPath, opp.OrgOpportunity__r.get(fsm.fieldPath));
// 1件でも追加された場合は更新用のリストへ加える
addFlg = true;
}
}
// 更新対象のみupdate用リストにくわえる
if (addFlg) updateList.add(opp);
}
// 子商談を更新する
if (!updateList.isEmpty()) update updateList;
}
全体のソースとか説明はこちら