AXForum  
Вернуться   AXForum > Блоги > CRM, SharePoint и Черная Магия
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

Добро пожаловать в мой блог! Изначально он не задумывался как блог CRM разработчика, но жизнь сама внесла нужные коррективы. Тут я публикою все свои наблюдения относительно обозначенных в заголовке систем. Если Вы найдете в нем что-то интересное для Вас, как для заказчика, то буду рад сотрудничать с Вами! В моей компетенции 100% задач по MS CRM 3.0/4.0/2011:
  • Консалтинг
  • Проектирование
  • Разработка
  • Обучение


MVP 2010, 2011
Оценить эту запись

Укрощение Advanced Find, часть 1

Запись от Артем Enot Грунин размещена 19.10.2009 в 12:49
Обновил(-а) Артем Enot Грунин 22.10.2009 в 21:57

Дополнение от 21.10.09 Автора изложенного метода зовут Dave Berry. Исходный пост: http://crmentropy.blogspot.com/2009/...nced-find.html

Однажды у нас был заказчик, который рассчитывал использовать CRM для автоматизации операционной деятельности. Его бизнес был связан с недвижимостью, так что каждый день в компанию обращалось большое клиентов и каждый мог быть значим, однако 90% заявок были чистым мусором. Требовалась система обработки и фильтрации обращений. Тогда ко мне пришла мысль сделать на форме Заявки-Интереса кнопку которая вызывала бы окно расширенного поиска, где бы уже был настроен нужный поисковый запрос с параметрами из заявки: тип недвижимости, район, площадь и т.д., чтобы принявший заявку менеджер мог быстро приступить к поиску и проработке вариантов. Тогда я впервые столкнулся с данной проблемой: в диалог расширенного поиска невозможно передать параметры поддерживаемым методом. Форум тоже молчал. Более или менее полноценное решение я нашел лишь недавно. Многие из вас могут помнить пост Адди Катца: Microsoft Dynamics CRM 4.0 - Unleashed: Display Fetch in Iframe, однако вы так же должны помнить что у него куча шероховатостей: не работают кнопки, не обновляется список (уже исправлено) и самое главное - не открываются по клику найденные записи. Неделю назад мне попался другой интересный пост с ссылкой на несуществующий ныне блог: http://6ix4our.blogspot.com/2009/03/...d-find_12.html. К счастью, на форумах нашлись его реплики: https://community.dynamics.com/forum...430/20444.aspx.
Код:
/// Summary:
/// Provides a mechanism for replacing the contents of any Iframe on an entity form
/// with any Advanced Find view.
///
/// Param Description
/// ---------- -------------------
/// iFrameId The id established for the target Iframe
/// entityName The name of the entity to be found by the Advanced Find
/// fetchXml FetchXML describing the query for the entity
/// layoutXml LayoutXML describing the display of the entity
/// sortCol The schema name of the entity attribute used for primary sorting
/// sortDescend "true" if sorting the sortCol by descending values, or "false" if ascending
/// defaultAdvFindViewId The GUID of an Advanced Find View for the entity; may that of a saved view
/// entityTypeId (Optional) The Object Type ID for the entity. Setting this causes the system
/// to overwrite the functionality of the "New" button to establish related records

function EmbedAdvancedFindView (iFrameId, entityName, fetchXml, layoutXml, sortCol, sortDescend, defaultAdvFindViewId, entityTypeId) {
// Initialize our important variables
var httpObj = new ActiveXObject("Msxml2.XMLHTTP");
var url = SERVER_URL + "/AdvancedFind/fetchData.aspx";
var iFrame = document.getElementById(iFrameId);
var win = iFrame.contentWindow;
var doc = iFrame.contentWindow.document;

// Provide a global function within the parent scope to avoid XSS limitations
// in updating the iFrame with the results from our HTTP request
PushResponseContents = function (iFrame, httpObj, entityTypeId) {
var win = iFrame.contentWindow;
var doc = iFrame.contentWindow.document;
var m_iFrameShowModalDialogFunc = null;
var m_windowAutoFunc = null;

// Write the contents of the response to the Iframe
doc.open();
doc.write(httpObj.responseText);
doc.close();

// Set some style elements of the Advanced Find window
// to mesh cleanly with the parent record's form
doc.body.style.padding = "0px";
doc.body.scroll="no";

// Should we overwrite the functionality of the "New" button?
if ((typeof(entityTypeId) != "undefined") && (entityTypeId != null)) {
var buttonId = "_MBopenObj" + entityTypeId;
var newButton = doc.getElementById(buttonId);

eval("newButton.action = 'locAddRelatedToNonForm(" + entityTypeId + ", " + crmForm.ObjectTypeCode + ", \"" + crmForm.ObjectId + "\",\"\");'");
}

// Swap the showModalDialog function of the iFrame
if (m_iFrameShowModalDialogFunc == null) {
m_iFrameShowModalDialogFunc = win.showModalDialog;
win.showModalDialog = OnIframeShowModalDialog;
}

if (m_windowAutoFunc == null) {
m_windowAutoFunc = win.auto;
win.auto = OnWindowAuto;
}

// Configure the automatic refresh functionality for dialogs
function OnIframeShowModalDialog(sUrl, vArguments, sFeatures) {
m_iFrameShowModalDialogFunc(sUrl, vArguments, sFeatures);
doc.all.crmGrid.Refresh();
}

function OnWindowAuto(otc) {
doc.all.crmGrid.Refresh();

m_windowAutoFunc(otc);
}
}

// Without a null src, switching tabs in the form reloads the src
iFrame.src = null;

// Preload the iFrame with some HTML that presents a Loading image
var loadingHtml = ""
+ "<table height='100%' width='100%' style='cursor:wait'>"
+ " <tr>"
+ " <td valign='middle' align='center'>"
+ " <img alt='' src='/_imgs/AdvFind/progress.gif' />"
+ " <div /><i>Loading View...</i>"
+ " </td>"
+ " </tr>"
+ "</table>";

doc.open();
doc.write(loadingHtml);
doc.close();

// Compile the FetchXML, LayoutXML, sortCol, sortDescend, defaultAdvFindViewId, and viewId into
// a list of params to be submitted to the Advanced Find form
var params = "FetchXML=" + fetchXml
+ "&LayoutXML=" + layoutXml
+ "&EntityName=" + entityName
+ "&DefaultAdvFindViewId=" + defaultAdvFindViewId
+ "&ViewType=1039" // According to Michael Hohne over at Stunnware, this is static
+ "&SortCol=" + sortCol
+ "&SortDescend=" + sortDescend;

// Establish an async connection to the Advanced Find form
httpObj.open("POST", url, true);

// Send the proper header information along with the request
httpObj.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
httpObj.setRequestHeader("Content-length", params.length);

// Function to write the contents of the http response into the iFrame
httpObj.onreadystatechange = function () {
if (httpObj.readyState == 4 && httpObj.status == 200) {
parent.PushResponseContents(iFrame, httpObj, entityTypeId);
}
}

// Set it, and forget it!
httpObj.send(params);
}
Функция натравливается на Iframe в котором предполагается показывать результаты. Параметрами передаются XML с Fetch и Layout запросами, а так же флаги сортировки и пр. параметры. Судя по всему параметры SortCol и SortDescend рудиментарные (остались от старых версий), так как они уже содержатся в запросе, а на самой форме не заполняются. Что удобно, данная ф-ция полностью избавляет нас от необходимости как-то отслеживать состояние фрейма или править ее реализацию в зависимости от того на какой вкладке он расположен - скопировал, вставил, забыл.
Для простоты получения нужных параметров можно воспользоваться следующим кодом:
Код:
javascript:window.clipboardData.setData("Text", "var fetchXml =\'" + advFind.FetchXml + "\';\n\n" + "var layoutXml =\'" + advFind.LayoutXml + "\';\n\n" + "var entityName =\'" + advFind.EntityName + "\';\n\n" + "var sortCol=\'" + advFind.SortCol + "\';\n\n" + "var sortDescend=\'" + advFind.SortDescend+ "\';\n\n" + "var defaultAdvancedFindViewId =\'" + advFind.DefaultAdvancedFindViewId + "\';\n\n EmbedAdvancedFindView (IFrame_af, entityName, fetchXml, layoutXml, sortCol, sortDescend, defaultAdvFindViewId);");
Чтобы им воспользоваться скопируйте код в буфер, откройте или настройте нужное вам поисковое представление, после чего вставьте код в строку браузера и запустите. Если все было сделано правильно, браузер отобразит true, а в буфер будет скопирован (в зависимости от настроек безопасности, может потребоваться разрешение на доступ к буферу - просто согласитесь) результат выполнения кода:
Код:
  var fetchXml ='<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false"><entity name="account"><attribute name="name"/><attribute name="primarycontactid"/><attribute name="statuscode"/><attribute name="accountid"/><order attribute="name" descending="false"/><filter type="and"><condition attribute="creditlimit" operator="ge" value="123"/></filter></entity></fetch>';
  
  var layoutXml ='<grid name="resultset" object="1" jump="name" select="1" icon="1" preview="1"><row name="result" id="accountid"><cell name="name" width="150"/><cell name="primarycontactid" width="150"/><cell name="statuscode" width="100"/></row></grid>';
  
  var entityName ='account';
  
  var sortCol='undefined';
  
  var sortDescend='undefined';
  
  var defaultAdvancedFindViewId ='{00000000-0000-0000-00AA-000000666000}';
  
   EmbedAdvancedFindView (IFrame_af, entityName, fetchXml, layoutXml, sortCol, sortDescend, defaultAdvFindViewId);
Как я уже говорил, sortCol и sortDescend на форме не заполняются, так что их вам придется заполнить руками.
Удачного фетча!
Размещено в CRM
Просмотров 28467 Комментарии 0
Всего комментариев 0

Комментарии

 


Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 01:48.