Добро пожаловать в мой блог! Изначально он не задумывался как блог CRM разработчика, но жизнь сама внесла нужные коррективы. Тут я публикою все свои наблюдения относительно обозначенных в заголовке систем. Если Вы найдете в нем что-то интересное для Вас, как для заказчика, то буду рад сотрудничать с Вами! В моей компетенции 100% задач по MS CRM 3.0/4.0/2011:
MVP 2010, 2011
- Консалтинг
- Проектирование
- Разработка
- Обучение
MVP 2010, 2011
Укрощение Advanced Find, часть 1
Запись от Артем Enot Грунин размещена 19.10.2009 в 12:49
Обновил(-а) Артем Enot Грунин 22.10.2009 в 21:57
Обновил(-а) Артем Enot Грунин 22.10.2009 в 21:57
Теги advanced find, java script, unsupport
Дополнение от 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.
Функция натравливается на Iframe в котором предполагается показывать результаты. Параметрами передаются XML с Fetch и Layout запросами, а так же флаги сортировки и пр. параметры. Судя по всему параметры SortCol и SortDescend рудиментарные (остались от старых версий), так как они уже содержатся в запросе, а на самой форме не заполняются. Что удобно, данная ф-ция полностью избавляет нас от необходимости как-то отслеживать состояние фрейма или править ее реализацию в зависимости от того на какой вкладке он расположен - скопировал, вставил, забыл.
Для простоты получения нужных параметров можно воспользоваться следующим кодом:
Чтобы им воспользоваться скопируйте код в буфер, откройте или настройте нужное вам поисковое представление, после чего вставьте код в строку браузера и запустите. Если все было сделано правильно, браузер отобразит true, а в буфер будет скопирован (в зависимости от настроек безопасности, может потребоваться разрешение на доступ к буферу - просто согласитесь) результат выполнения кода:
Как я уже говорил, sortCol и sortDescend на форме не заполняются, так что их вам придется заполнить руками.
Удачного фетча!
Однажды у нас был заказчик, который рассчитывал использовать 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); }
Для простоты получения нужных параметров можно воспользоваться следующим кодом:
Код:
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);");
Код:
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);
Удачного фетча!
Всего комментариев 0