Dynamics CRM 4 では、 エンティティのフォームで表示されるLookup属性のフィールドは参照先エンティティの主属性が表示されます。MSDNのブログで主属性以外を表示する方法が掲載されていましたので、紹介します。ネタ元のサイトは次のサイトです。というか今回掲載するサンプルはほぼそのまんまです。
How to display related entity field in a CRM Lookup instead of the primary entity field?
http://blogs.msdn.com/b/paf/archive/2009/04/22/how-to-display-related-entity-fields-in-a-crm-lookup-attribute-instead-of-the-primary-entity-field.aspx
今回のサンプルを実装すると次のように、取引先企業の親会社Lookup属性に、取引先企業名ではなく、企業コードを表示することができます。
主属性を任意の属性を表示できるようになると次のような素敵なことになるきがします。
主属性には一意のコードを設定して、エンティティフォームではユーザフレンドりなテキストを表示するようにすると、Dynamics CRM 標準のインポートでLookupフィールドの解決で苦労することがなくなります。主属性が重複するとインポート時に参照先データが解決できなくなるためです。
また、グローバル対応ようにマスタ用のエンティティに各言語用の表示用の属性を定義しておくことで、Lookupフィールドの値がグローバル対応できるようになります。
動作確認はオールインワン環境上に構築した Dynamics CRM 4 UpdateRollup 8 の環境で実施しています。
1.フォームのOnLoadイベントで、javascript を追加
エンティティフォームのOnLoad イベントで次のステートメントを追加します。
crmForm.all.LookupSchemaName.FireOnChange();
LookupSchemaName は、Lookup属性のスキーマ名です。取引先企業の取引先企業の親会社のLookup属性フィールドに主属性以外のフィールドを表示する場合は OnLoad イベントに次の文を追加します。
crmForm.all.parentaccountid.FireOnChange();
FireOnChange()を呼び出すことで、OnChangeイベントを起動し初期表示時に企業コードをLookupフィールドに設定するようにさせます。
2.Lookup属性フィールドのOnChangeイベントにLookup先エンティティの属性を検索し設定する処理を設定
次のスクリプトを Lookup属性に表示する属性を変更した Lookupフィールドの OnChange イベントに貼り付けます。スクリプトはサンプルとほぼ同じですが一部修正しています。次の変数の値を変更して任意のLookupフィールドで主属性以外の属性を表示できるようになります。
変数 | 設定値 |
fieldToDisplay | 表示したいLookup先エンティティの属性名(サンプルでは accountnumber) |
fieldToDisplayIsText | 表示する属性がnvarchar の場合は true, picklist や lookupフィールドの場合は false を指定する。(サンプルでは true ) |
organizationName | 組織名を指定する。サンプルではエンティティフォームのグローバル変数 ORG_UNIQUE_NAME を設定 ) |
var fieldToDisplay = 'accountnumber'; var fieldToDisplayIsText = true; var organizationName = ORG_UNIQUE_NAME; var lookupData = new Array(); var lookupItem= new Object(); var lookup = event.srcElement.DataValue; if (typeof(lookup) != 'undefined' && lookup != null && lookup[0] != null) { var myValue = GetAttributeValueFromID(lookup[0].typename,lookup[0].id,fieldToDisplay,fieldToDisplayIsText); if(myValue != '') { lookupItem.id = lookup[0].id; lookupItem.typename = lookup[0].typename; lookupItem.name = myValue; lookupData[0] = lookupItem; crmForm.all[event.srcElement.id].DataValue = lookupData; } } function GetAttributeValueFromID(sEntityName, sGUID, sAttributeName, isTextField) { var xml = "" + "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" + GenerateAuthenticationHeader() + " <soap:Body>" + " <Execute xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" + " <Request xsi:type=\"RetrieveRequest\" ReturnDynamicEntities=\"false\">" + " <Target xsi:type=\"TargetRetrieveDynamic\">" + " <EntityName>" + sEntityName + "</EntityName>" + " <EntityId>" + sGUID + "</EntityId>" + " </Target>" + " <ColumnSet xmlns:q1=\"http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:ColumnSet\">" + " <q1:Attributes>" + " <q1:Attribute>" + sAttributeName + "</q1:Attribute>" + " </q1:Attributes>" + " </ColumnSet>" + " </Request>" + " </Execute>" + " </soap:Body>" + "</soap:Envelope>" + ""; var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP"); xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false); xmlHttpRequest.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Execute"); xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8"); xmlHttpRequest.setRequestHeader("Content-Length", xml.length); xmlHttpRequest.send(xml); var result = null; try{ // 属性値がnullだとノードが存在しないため、例外処理で対応 if(isTextField){ result = xmlHttpRequest.responseXML.selectSingleNode("//q1:" + sAttributeName).text; } else { result = xmlHttpRequest.responseXML.selectSingleNode("//q1:" + sAttributeName).getAttribute('name'); } }catch(e){ } if (result == null) { return ''; } else{ return result; } }
3. まとめ
説明は以上です。 Lookup 属性を主属性以外の属性を表示できるようにすると, 英語表示用の属性を用意しておき、フォーム表示時にLookupの表示内容を英語表示用の属性にすることで擬似的にグローバル対応を実装できます。Lookup属性に主属性以外を表示できるテクニックは意外と役にたつのではと思います。 余分に Webサービスを呼び出すことになるので、やりすぎはよくないと思いますが。
さんのコメント: さんのコメント: