К сожалению, в MS CRM 3.0 нет возможности связывать сущности отношением многие-ко-многим. И это не очень удобно. Например, когда на форме Вы хотите сделать возможность выбора нескольких контактов, то стандартными инструментами реализовать это никак не получится.

Чтобы решить эту проблему обычно предлагают создавать новую сущность и копировать в нее все необходимые записи для выбора. Таким образом, чтобы вывести на форме 2 лукапа с возможностью выбора контакта в каждом из них, необходимо создать новую сущность new_contact, связать ее со стандартной contact и создавать новые записи, привязывая их к записям из стандартной.

Но есть и другой способ – использовать метод, предложенным неким Death Angel, за что ему огромное спасибо!
Вот, собственно его функция:

function Text_To_LookUp(sFieldName, sLookuptype, sEntity, sOnChangeCode, oGUID, sDisplayText, sFilters)
{

var sIcons = «/_imgs/»;
var sLookupTypeNames = «»;
var sLookupClass = «»;

if (sEntity.substr(0,4) == «new_»)
{
sIcons += «icon.aspx?objectTypeCode=» + sLookuptype + «&iconType=GridIcon&inProduction=1&cache=1″;
sLookupTypeNames = » lookuptypenames=’» + sEntity + «:» + sLookuptype + «‘ «;
}
else
{
sLookupClass = » lookupclass=’» + sEntity + «‘ «;
sIcons += «ico_16_» + sLookuptype + «.gif»;
}

if (sOnChangeCode != null && sOnChangeCode != «»)
sOnChangeCode = «onChange=\» return » + sOnChangeCode + «\»";

var New_HTML = «» ;
var Div_HTML = «» ;
//alert(oGUID);

Div_HTML = «<DIV class=lu>»;
//if (oGUID.length !== 0)
if (oGUID != 0)
{
Div_HTML += «<SPAN class=lui onclick=\’openlui();\’ otype=\’» + sLookuptype + «\’ oid=\’» + oGUID + «\’ otypename=\’» + «contact» + «\’>»;
Div_HTML += «<IMG class=lui src=\’» + sIcons + «\’>»;
Div_HTML += sDisplayText;
Div_HTML += «</SPAN>»;
}
else
{
Div_HTML += «&nbsp;»;
}
Div_HTML += «</DIV>»;

New_HTML += «<table class=’lu’ cellpadding=’0′ cellspacing=’0′ width=’100%’ style=’table-layout:fixed;’>»;
New_HTML += «<tr>»;
New_HTML += «<td>»;
New_HTML += Div_HTML;
New_HTML += «</td>»;
New_HTML += «<td width=’25′ style=’text-align: right;’>»;
New_HTML += «<img src=’/_imgs/btn_off_lookup.gif’ id=’» + sFieldName + «‘ class=’lu’ tabindex=’1000′ lookuptypes=’» + sLookuptype + «‘ » + sLookupTypeNames + » lookuptypeIcons=’» + sIcons + «‘ » + sLookupClass + » lookupbrowse=’0′ lookupstyle=’single’ defaulttype=’0′ req=’0′ » + sOnChangeCode + «>»;
New_HTML += «</td>»;
New_HTML += «</tr>»;
New_HTML += «</table>»;

//alert(New_HTML);
var field = crmForm.elements[sFieldName];

field.insertAdjacentHTML(«afterEnd»,New_HTML)
field.parentNode.removeChild(field);
field = crmForm.elements[sFieldName];
field.value = oGUID;

//Add filters to lookup box
if (sFilters !=null && sFilters != «»)
{
field.lookupbrowse = 1;
field.additionalparams = ‘fetchXml=’ + sFilters;
}
}

Параметры:

  1. sFieldName : имя текстового поля, в котором будет эмулироваться lookup
  2. sLookuptype : тип лукапа ( код сущности)
  3. sEntity : имя сущности
  4. sOnChangeCode : javascript-код для работы события OnChange() (его эмуляции)
  5. oGUID : GUID сущности, которая будет загружена в лукапе
  6. sDisplayText : текст, который будет отображаться в лукапе
  7. sFilters : возможность фильтрации для лукапа

Пример вызова функции (на событие OnLoad):

//вызываю функцию с нужными параметрами
Text_To_LookUp("new_aktest", "1088", "SalesOrder","", crmForm.all.new_aktest.datavalue,crmForm.all.new_aktests.value, akfilter);

Для работы с этой функцией необходимо сделать следующее:

  1. создать текстовое поле
  2. разместить его на форме
  3. в событие OnLoad() формы вставить функцию и ее вызов
  4. Опубликовать изменения.

У меня не получилось передвать в функцию 4й параметр для эмуляции события OnChange () (нажатие на лукап), поэтому я использовал следующий код:

// симулирую событие onChange()
function onChangeAk()
{
var S_CONTACT_NAME = crmForm.all.new_aktest.parentElement.parentElement.firstChild.innerText;
crmForm.all.new_aktests.value = S_CONTACT_NAME;
}

//вызываю функцию с нужными параметрами
Text_To_LookUp(«new_aktest», «1088″, «SalesOrder»,»", crmForm.all.new_aktest.datavalue,crmForm.all.new_aktests.value, «»);

// «присоединяю» событие OnChange() к необходимому полю-лукапу и вызываю нужную функцию
oRec1 = crmForm.all.new_aktest;
oRec1.attachEvent(«onchange»,onChangeAk);

В этом примере, в поле new_aktest будет храниться GUID записи (если сущность contact, то значение contactid). Поэтому, чтобы сохранять текстовое значение поля приходиться создавать дополнительный текстовый атрибут new_aktests, в котором сохраняю текстовое значение.

Параметр sFilters позволяет передавать определенное условие фильтрации лукапа с помощью FetchXML. Этот вариант я опишу в следующий раз.

Для большинства задач функция подходит, не получилось привязаться к системным сущностям: Product, User.
UPD. Везде используются обычные кавычки вида «