Фильтрация полей Lookup в CRM 4
Псевдофильтр
Когда Вы открываете лукап появляется диалоговое окно содержащее строку поиска и представление. Так вот, у всех представлений есть поля по которым осуществляется поиск. Ими мы и воспользуемся для того, чтобы отобрать нужные нам записи.
- Предположим, что у нас есть два объекта – Регион и Город – Регион является родительским по отношению к Город, т.е. в объекте Город есть лукап на объект Регион. Откройте в объекте Город представление «Город представление поиска» и добавьте еще один столбец поиска: «Регион»;
- Теперь вынесем оба эти объекта (Регион и Город) в виде лукапов на форму какого-либо третьего объекта (например Бизнес-партнера). На onload формы третьего объекта вешаем следующий скрипт:
document.FilterLookup = function(source, target) { if (IsNull(source) || IsNull(target)) { return; } var name = IsNull(source.DataValue) ? '' : source.DataValue[0].name; name=escape(name); target.additionalparams = 'search=' + name; }
- А на событие onchange лукапа Регион добавьте следующий код (т.к. этот код передает в скрипт на онлоаде два параметра – что фильруем и где фильтруем – то аналогичным способом можете повесть фильтр и на другие лукапы на данной форме):
document.FilterLookup(crmForm.all.new_stateid, crmForm.all.new_cityid);
- Когда пользователь выберет Регион, а затем попытается выбрать Город, то поле поиска у него уже будет заполнено значением поля Регион И соответственно все записи в представлении будут отобраны по указанному региону. Только учтите, что поиск осуществляется по двум полям (в этом примере – в Вашем может быть и больше) – Имя и Регион – таким образом если поле Имя совпадет с введенной строкой поиска, то эта строчка также будет отображена, вне зависимости от значения столбца Регион.
Жесткий фильтр
Этот пример отличается от предыдущего тем, что мы жестко задаем условия отбора и не позволяем выбрать никакие другие записи. Недостатком этого метода является, то что при этом мы лишаемся строки поиска и в случаи большого количества записей в диалоговом окне поиска лукапа нам предстоит методом перебора отыскивать нужные.
- Сначала подправим исходный файл CRM. Следующий код должен быть помещен где-нибудь в файле <папка сайта CRM>\_controls\lookup\lookupsingle.aspx:
<script runat="server"> protected override void OnLoad( EventArgs e ) { base.OnLoad(e); crmGrid.PreRender += new EventHandler( crmgrid_PreRender ); } void crmgrid_PreRender( object sender , EventArgs e ) { //Поскольку мы не хотим испортить другие лукапы, проверяем, что параметр search начинается с <fetch if (crmGrid.Parameters["search"] != null && crmGrid.Parameters["search"].StartsWith("<fetch")) { crmGrid.Parameters.Add("fetchxml", crmGrid.Parameters["search"]); crmGrid.Parameters.Remove("searchvalue"); //Чтобы юзверы не смогли создать новую запись из лукапа и выбрать ее – скрываем кнопку создания новой записи this._showNewButton = false; } } </script>
- Далее мы должны передать в лукап (который мы немного подправили 🙂 ) fetchxml строку для отбора нужных записей – соответственно сначала Вы должны ее составить (в этом примере на объекте Контакт отбираются Родительcкие клиенты, которые являются только Бизнес-партнерами и имеют название Газпром). Подробнее об fetchxml читайте в статье FetchXML, а о том как автоматизировать их создание смотрите инструмент FetchXML Builder. Поместите следующий код на онлоад того объекта, лукапы которого хотите фильтровать (измените только fetchxml строку и имя поля лукап):
var field = crmForm.all.parentcustomerid; //Отключаем поле поиска в диалоговом окне лукапа field.lookupbrowse = 1; //Передаем fetch xml через параметр поиска лукапа field.AddParam("search", "<fetch mapping='logical'><entity name='account'>" + "<filter><condition attribute='name' operator='eq' value='Газпром' /></filter></entity></fetch>");
- При использовании этого способы Вы должны учитывать одну вещь – он никак не влияет на автоматическое заполнение и на помощника форм. Поэтому, чтобы исключить возможность обхода Вашего фильтра Вы должны отключить эти компоненты.
По первому варианту лучше добавить escape(name);
Чтобы не было проблем с кодировкой русских букв. Я у себя описывал
http://ms-dynamics-crm.com.ua/2009/02/16/filter-in-microsoft-dynamics-crm-40/
Пятая строчка сверху 🙂
name=escape(name);
Сорри за невнимательность 🙂
Я сначала тоже взял код без escape 🙂 но вместо кирилицы были квадратики 🙂 пришлось штудировать мануалы по яваскрипту 🙂
Хочу заметить, что данный код не работает, если в названии обоих полей присутствует id, к примеру: customerid и responsiblecontactid. Код приводит к ошибке на странице.
Наверно тут дело не в id 🙂 а в том, что Вы пытаетесь фильтровать мульти-лукапы 🙂 а в данном случаи мы редактировали только lookupsingle.aspx, который отвечает за единичные лукапы 🙂
а как сделать чтобы и в помощнике по созданию форм работало?
Пока встречать такой реализации не приходилось!
М возвращаясь к августу. Как побороть ошибку при фильтрации лукапов?
Боюсь, что вопрос не ясен? о какой ошибке идет речь?
Речь об ошибке, о которой написал Андрей Мурзин 18.08.2009.
У меня тоже была такая ошибка, помогло перенести функцию из document в window.
На onload формы пишем
window.FilterLookup = function(source, target)
{
……..
}
и на onchange исправляем
FilterLookup(…,…)
У меня это решило проблему.
Добрый день!
Подскажите можно ли использовать 1 часть поста — Псевдофильтр и передавать ему несколько параметров, к примеру:
нужно получить города не 1 области, а 2 или 3, и как тогда передавать значения для фильтрации?
Добрый день. Не думаю что такое возможно. Тут нужно использовать 2-ой способ.
Здравствуйте.
Сделали по вышеописанному методу фильтр на лукап возможных сделок. Все работает отлично. Но тут появилась обратная задача. По умолчанию поиск сделок отображает только открытые сделки. Шаманство с фильтрами на statuscode и statecode по аналогии с обычными фильтрами ни к чему не привело. Есть ли какая-нибудь возможность при лукапе отображать и завершенные сделки?
Добрый день 🙂
http://mmcrm.ru/?p=1071
http://mmcrm.ru/?p=624
Спасибо!
Добрый день!
столкнулся со следующей проблемой и буду примного признателен за любую помощь.
при открытии некоторых контрактов возникает ошибка:
Microsoft CRM Error Report:
Error Description:
An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Error Details:
Exception of type ‘System.Web.HttpUnhandledException’ was thrown.
Full Stack:
[ArgumentException: This lookup can only display one item. Lookup ID = customer]
at Microsoft.Crm.Application.Components.Sdk.FormControls.Web.PartyListControl.set_Value(Object value)
at Microsoft.Crm.Application.Components.Sdk.FormControls.Web.CrmWebFormDataControlUIWrapper.SetValue()
at Microsoft.Crm.Application.Forms.EndUserForm.BindDataRecursively(Control control)
at Microsoft.Crm.Application.Forms.EndUserForm.BindDataRecursively(Control control)
at Microsoft.Crm.Application.Forms.EndUserForm.BindDataRecursively(Control control)
at Microsoft.Crm.Application.Forms.EndUserForm.BindDataRecursively(Control control)
at Microsoft.Crm.Application.Forms.EndUserForm.BindDataRecursively(Control control)
at Microsoft.Crm.Application.Forms.EndUserForm.BindDataRecursively(Control control)
at Microsoft.Crm.Application.Forms.CustomizableForm.Execute(Entity entity, String formType)
at Microsoft.Crm.Web.MA.CampaignResponseDetailPage.ConfigureForm()
at Microsoft.Crm.Application.Controls.AppUIPage.OnPreRender(EventArgs e)
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
[HttpUnhandledException: Exception of type ‘System.Web.HttpUnhandledException’ was thrown.]
at System.Web.UI.Page.HandleError(Exception e)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest()
at System.Web.UI.Page.ProcessRequest(HttpContext context)
at ASP.finam_ma_campaignresponse_edit_aspx.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Other Message:
Error Number:
Source File:
Not available
Line Number:
Not available
Date: 10-10-2011
Time: 20:22:27
Server: crm
Request URL:
http://crm:5555/FINAM/ma/campaignresponse/edit.aspx?id={ACB0418F-32F0-E011-8C0E-001A6433B300}&_CreateFromType=4&_CreateFromId={1CE5A959-49A7-4561-9A20-C19D7FCEF541}
судя по описанию, в поле lookup — customer сохранено более одного значения. в связи с чем это может происходить (не часто но периодически) и как это можно вылечить (возможно руками в бд)
Большое спасибо
Добрый день!
Боюсь что раньше с такой не сталкивался. Есть подобная только для CRM 3.0: http://kbalertz.com/914799/Error-message-appointment-Microsoft-Dynamics-lookup-display-Lookup.aspx
Вопрос по жесткому фильтру
Как сделать, чтобы в лукапе открывались только объекты, в которых ownerid = текущий пользователь?
(в ролях безопасности доступ на чтение, запись и т.п. к данному объекту открыт для всех пользователей)
Вам нужно сформировать фетч в котором отфильтровать записи по теущему пользователю. ID текущего пользователя можете вернуть с помощью WhoAmI (http://msdn.microsoft.com/en-us/library/bb890244.aspx).
Кстати, а какой запрос отправляется из веб-интерфейса на CRM-сервер, когда в расширенном поиске или представлении объекта настроен фильтр «владелец (ownerid) = текущий пользователь»?
кстати да 🙂 у Вас есть CRM 2011& сформируйте такой запрос в Расширенном поиске и посмотрите его фетч (для этого в Расширенном поиске предусмотрена специальная кнопка) 🙂
в том-то и беда, что 2011-го нет, надо реализовать все это на 4.0. Как вытащить передаваемый фетч-запрос в четверке?
Азат, для жесткого фильтра используйте фильтрацию с помощью плагина (http://mmcrm.ru/?p=1230)
Вытащить fetch можно следующим способом:
1. Открыть расширенный поиск.
2. Нажать комбинацию Ctrl+N.
3. Формируете условие.
4. Нажимаете «Найти», чтобы увидеть что вернул запрос. В адресную строку вставляете вот это:
javascript:alert(resultRender.FetchXml.value);
В сообщении будет fetch запрос.
ХЕЛП!((
Решение «Псевдофильтр» в моей ситуации идеально! Но но всей видимости после какого то ролапа не поддерживается, Есть ли подобная альтернатива??
Ложная тревога) Был невнимателен, всё работает !! 🙂