少し複雑な構造や入力規則を持っているカスタムオブジェクトを利用している場合には、
登録、編集画面をVisualforceで作成する場合があります。
私の参加するプロジェクトでもそのようなことをしていたのですが、既にあるレコード
を複製して新しいレコードを作る場合に、少し問題が起こったので、調査したことと、
解決策をメモしておきます。
問題の原因は、カスタムオブジェクトの設定「標準ボタンと標準リンク」のところに、
新規(New)と編集(Edit)にはVisualforce ページが設定してあったのに、コピー(Clone)
のところには標準 Salesforce.com ページが設定してあったために、オブジェクトの
コピーがきちんと行われていなかったためでした。
Cloneが中途半端に行われていたため、空欄の項目ができてしまったいたようです。
そのため、VisualforceとApexコードでコピー機能を実装することに。。
オブジェクトの複製(クローン)について
Salesforceでは、以下のようなコードでオブジェクト、カスタムオブジェクトの複製が可能です。
Account originAccount = [SELECT id, name FROM Account LIMIT 1]; Account cloneAccount = new Account(); cloneAccount = originAccount.clone(false,true);
clone(false,true)
の1つ目の引数は、Salesforceのオブジェクトidをコピーするか/しないかを指定します。
・trueの場合・・・idをコピーします。
・falseの場合・・・idをコピーせず、それ以外の項目をコピーします。
2つめの引数は、新しいオブジェクトとしてクローン作成するかどうかを指定します。
・trueの場合・・・作成元のオブジェクトの参照は引き継がず、値だけをコピーして新しいオブジェクトを作成します。
・falseの場合・・・作成元のオブジェクトの参照を引き継いで新しいオブジェクトを作成します。
今回は、既存のレコードを元に「複製」するので、idはコピーしないよう、1つ目の引数はfalseとしました。
trueとしてしまうと、元のidのオブジェクトに変更を加えることになりますので、「更新」になってしまいます。
また、作成元のオブジェクトの参照を引き継いで新しいオブジェクトを作成した場合、
新しいオブジェクトの値を変更すると作成元のオブジェクトの値も変更されてしまいますので、2つめの引数はtrueとしました。
呼ばれたボタンが、編集なのか、コピーなのかを判断する。
今回、編集時とコピー時は同じVisualforceの画面を利用しようと思います。
そのためには、画面がどのボタンを押して呼ばれたのかを判断しなければいけませんね。
そこで、以下のログを仕込んで、呼ばれた時のパラメータの違いを見てみました。
for (string key: ApexPages.currentPage().getParameters().keySet()){ if (ApexPages.currentPage().getParameters().get(key) != null){ system.debug(Logginglevel.INFO,'■' + key + ' = ' + ApexPages.currentPage().getParameters().get(key)); } }
すると、
新規の場合 14:43:32.057 (57825000)|USER_DEBUG|[30]|INFO|■retURL = /aXX/o 14:43:32.057 (57927000)|USER_DEBUG|[30]|INFO|■save_new = 1 14:43:32.058 (58008000)|USER_DEBUG|[30]|INFO|■sfdc.override = 1 編集の場合 14:35:25.114 (114702000)|USER_DEBUG|[30]|INFO|■id = aXXX0000000PXXX 14:35:25.114 (114812000)|USER_DEBUG|[30]|INFO|■retURL = /aXXX0000000PXXX 14:35:25.114 (114897000)|USER_DEBUG|[30]|INFO|■scontrolCaching = 1 14:35:25.114 (114986000)|USER_DEBUG|[30]|INFO|■sfdc.override = 1 コピーの場合 14:35:30.093 (93392000)|USER_DEBUG|[30]|INFO|■clone = 1 14:35:30.093 (93496000)|USER_DEBUG|[30]|INFO|■id = aXXX0000000PXXX 14:35:30.093 (93583000)|USER_DEBUG|[30]|INFO|■retURL = /aXXX0000000PXXX 14:35:30.093 (93665000)|USER_DEBUG|[30]|INFO|■scontrolCaching = 1 14:35:30.093 (93744000)|USER_DEBUG|[30]|INFO|■sfdc.override = 1
のようなログが出力されます。
コピーの場合は「clone = 1」というパラメータが渡っているようですね。
そのため、以下のように実装しました。
if(Apexpages.currentPage().getParameters().get('clone')=='1'){ system.debug(Logginglevel.INFO,'★コピー'); SO = cloneObj; }else{ system.debug(Logginglevel.INFO,'★コピー以外(新規または編集)'); SO = originalObj; }
こうすると、編集の時には、idを引き継いでいるため更新となり、コピーの時には、
idが新しく採番されるので、複製となります。
コラム
salesforce関連の本って少ないですよね。また、Web上の情報は詳しいのですが、広大すぎて、調べようと思ったときに手元にリファレンス的な本があると助かります。以下は私のおすすめの本です。
Force.comのすべて ~設計・開発 実践マニュアル~ 初めてSalesForceでWebアプリを作ろうとしたとき、どこから手を付けていいか迷いました。そんなときに役立つ初心者向けの本です。細かいところに手が届くたぐいの本ではないですが、一通り、体系的に学べるので、役に立ちます。
改訂新版 Salesforceプログラミングバイブル すこし高い本ですが、豊富なソースが載っており、上の本を勉強して次の段階に進んだ技術者には役立。こんなことってSalesForceでできないの?と思ったときにも役に立ちます。