sexta-feira, 10 de agosto de 2012
Corretor Ortográfico no Browser
Segue uma dica interessante, que é possibilidade de correção ortográfica no seu Browser. Para isto, basta instalar um Add-On gratuito da empresa Speckie e pronto.
Veja a matéria na Fonte, onde este recurso é usado no Microsoft Dynamics CRM.
[]s
quarta-feira, 25 de julho de 2012
Windows Phone - Application Life Cycle
Segue mais uma artigo sobre desenvolvimento no Windows Phone. Desta vez, analisaremos um ponto vital no desenvolvimento para esta plataforma, o Ciclo de Vida de Uma Aplicação.
Segue link do meu artigo publicado no Windows Phone Brasil !
[]s
sexta-feira, 13 de julho de 2012
Desenvolvimento Windows Phone - Primeiros Passos
Conforme o tempo permitir estarei publicando uma série de artigos sobre desenvolvimento para Windows Phone.
Matéria não falta, existe um "mundo" de informações técnicas sobre esta nova tecnologia, que cresce a cada dia!
Segue link do meu artigo no Blog do Windows Phone Brasil !
Abraços!
terça-feira, 10 de janeiro de 2012
CRM 2011 >> SubGrid - Totalização de Valor (via JScript)
No CRM 2011 temos a possibilidade de explorar muito bem desenvolvimentos em JScript, jQuery, jSon (ou REST OData).
Seguindo esta linha, segue um código, pequeno inclusive, que faz uma Totalização de Valores, buscando as informações em um SubGrid!
Para a execução do código, basta adicioná-lo no formulário, e chamá-lo no método OnLoad.
Importante adicionar os JScripts prontos da Microsoft, para execução de chamadas jQuery, sendo eles [jquery1.4.1.min.js] e [jqueryrestdataoperationfunctions.js].
Importante também adicionar o campo de moeda do CRM (TransactionCurrencyId), quando existir na tela do CRM algum campo do tipo moeda. Neste caso usaremos e o script abaixo preenche o campo automaticamente.
Estes arquivos podem ser encontrados no SDK do CRM (quando descompactado em qualquer diretório), no caminho [\SDK\samplecode\js\restendpoint\jqueryrestdataoperations\jqueryrestdataoperations\scripts].
Segue Script:
var timeOutVar;
function PrepareAddUpValue() {
var grid = document.getElementById('GRIDNAME');
if (grid == null)
{
// delay one second and try again.
timeOutVar = setTimeout(PrepareAddUpValue, 1000);
return;
}
clearTimeout(timeOutVar);
grid.attachEvent("onrefresh", AddUpValue);
}
function AddUpValue(){
var gridControl = document.getElementById("GRIDNAME").control;
var ids = gridControl.get_allRecordIds();
var new_total = 0.0;
for(var i = 0; i < ids.length; i++)
{
str_value = gridControl.getCellValue("NOME_COLUNA_GRID", ids[i]).replace("R$", "").replace(" ", "");
new_total += parseFloatString(str_value);
}
Xrm.Page.getAttribute("new_total").setValue(new_total);
Xrm.Page.data.entity.save();
}
function parseFloatString(str){
str = String(str);
var strNew = "";
for(var i=0; i < str.length; i++){
if (isNaN(parseInt(str.charAt(i))) == false) strNew +=str.charAt(i);
}
return parseFloat(strNew);
}
function SetCurrency(){
if (Xrm.Page.getAttribute("transactioncurrencyid") != null) return;
var filter = "?$select=TransactionCurrencyId,CurrencyName";
retrieveMultiple("TransactionCurrencySet", filter, retrieveMultipleCurrencyCompleted, null);
}
function retrieveMultipleCurrencyCompleted(data, textStatus, XmlHttpRequest){
if (data == null) return;
var idValue = data[0].TransactionCurrencyId;
var textValue = data[0].CurrencyName;
var thisEntityType = 'transactioncurrency';
Xrm.Page.getAttribute("transactioncurrencyid").setValue([{ id: idValue, name: textValue, entityType: thisEntityType }]);
}
SetCurrency();
Veja uma tela de exemplo. Note que, ao adicionar um novo registro, o Script é acionado, totalizando o valor em um campo do formulário. Isto acontece porque o Script atua no evento [OnRefresh] do SubGrid do CRM.
Seguindo esta linha, segue um código, pequeno inclusive, que faz uma Totalização de Valores, buscando as informações em um SubGrid!
Para a execução do código, basta adicioná-lo no formulário, e chamá-lo no método OnLoad.
Importante adicionar os JScripts prontos da Microsoft, para execução de chamadas jQuery, sendo eles [jquery1.4.1.min.js] e [jqueryrestdataoperationfunctions.js].
Importante também adicionar o campo de moeda do CRM (TransactionCurrencyId), quando existir na tela do CRM algum campo do tipo moeda. Neste caso usaremos e o script abaixo preenche o campo automaticamente.
Estes arquivos podem ser encontrados no SDK do CRM (quando descompactado em qualquer diretório), no caminho [\SDK\samplecode\js\restendpoint\jqueryrestdataoperations\jqueryrestdataoperations\scripts].
Segue Script:
var timeOutVar;
function PrepareAddUpValue() {
var grid = document.getElementById('GRIDNAME');
if (grid == null)
{
// delay one second and try again.
timeOutVar = setTimeout(PrepareAddUpValue, 1000);
return;
}
clearTimeout(timeOutVar);
grid.attachEvent("onrefresh", AddUpValue);
}
function AddUpValue(){
var gridControl = document.getElementById("GRIDNAME").control;
var ids = gridControl.get_allRecordIds();
var new_total = 0.0;
for(var i = 0; i < ids.length; i++)
{
str_value = gridControl.getCellValue("NOME_COLUNA_GRID", ids[i]).replace("R$", "").replace(" ", "");
new_total += parseFloatString(str_value);
}
Xrm.Page.getAttribute("new_total").setValue(new_total);
Xrm.Page.data.entity.save();
}
function parseFloatString(str){
str = String(str);
var strNew = "";
for(var i=0; i < str.length; i++){
if (isNaN(parseInt(str.charAt(i))) == false) strNew +=str.charAt(i);
}
return parseFloat(strNew);
}
function SetCurrency(){
if (Xrm.Page.getAttribute("transactioncurrencyid") != null) return;
var filter = "?$select=TransactionCurrencyId,CurrencyName";
retrieveMultiple("TransactionCurrencySet", filter, retrieveMultipleCurrencyCompleted, null);
}
function retrieveMultipleCurrencyCompleted(data, textStatus, XmlHttpRequest){
if (data == null) return;
var idValue = data[0].TransactionCurrencyId;
var textValue = data[0].CurrencyName;
var thisEntityType = 'transactioncurrency';
Xrm.Page.getAttribute("transactioncurrencyid").setValue([{ id: idValue, name: textValue, entityType: thisEntityType }]);
}
SetCurrency();
Veja uma tela de exemplo. Note que, ao adicionar um novo registro, o Script é acionado, totalizando o valor em um campo do formulário. Isto acontece porque o Script atua no evento [OnRefresh] do SubGrid do CRM.
terça-feira, 1 de novembro de 2011
>> VS.NET 2010 - Snippet Designer Plugin
Realmente facilita a "vida" ter a possibilidade de inserção de um código template complexo e longo com apenas uma chamada de [Shortcut no Code View] do Visual Studio. Este conceito é muito usado e se chama [Code Snippet].
Basicamente para criar um [fragmento de código] efetuarmos os seguintes passos:
1 - Criamos um arquivo XML;
2 - Primeiro adicionamos o Elemento CodeSnippets;
3 - Logo após adicionamos a seção Header;
4 - Depois adicionamos mais um elemento (<Snippet>) que conterá o Código Template;
5 - E por fim, salvamos o arquivo com a extensão .SNIPPET, no diretório de snippets no Visual Studio, geralmente em [C:\Users\[UserName]\Documents\Visual Studio 2010\Code Snippets\Visual C#\My Code Snippets].
Segue exemplo dos passos seguidos acima:
<CodeSnippets
xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>
My Snippet
</Title>
</Header>
<Snippet>
<Code Language="CSharp">
<![CDATA[MessageBox.Show("Hello World");]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
Porém, para facilitar ainda mais a vida do desenvolvedor, segue a dica do [Snippet Designer] que aumenta mais ainda a produtividade de criação de snippets, usando a IDE do Visual Studio.
Por exemplo, uma vez que você criou um código reutilizável, e gostaria de transformá-lo em um Snippet, com este Plugin basta selecionar seu código e exportá-lo como um snippet, como mostra a imagem abaixo:

Existem mais recursos interessantes, que estão documentados no link para baixar o Plugin.
Basicamente para criar um [fragmento de código] efetuarmos os seguintes passos:
1 - Criamos um arquivo XML;
2 - Primeiro adicionamos o Elemento CodeSnippets;
3 - Logo após adicionamos a seção Header;
4 - Depois adicionamos mais um elemento (<Snippet>) que conterá o Código Template;
5 - E por fim, salvamos o arquivo com a extensão .SNIPPET, no diretório de snippets no Visual Studio, geralmente em [C:\Users\[UserName]\Documents\Visual Studio 2010\Code Snippets\Visual C#\My Code Snippets].
Segue exemplo dos passos seguidos acima:
<CodeSnippets
xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>
My Snippet
</Title>
</Header>
<Snippet>
<Code Language="CSharp">
<![CDATA[MessageBox.Show("Hello World");]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
Porém, para facilitar ainda mais a vida do desenvolvedor, segue a dica do [Snippet Designer] que aumenta mais ainda a produtividade de criação de snippets, usando a IDE do Visual Studio.
Por exemplo, uma vez que você criou um código reutilizável, e gostaria de transformá-lo em um Snippet, com este Plugin basta selecionar seu código e exportá-lo como um snippet, como mostra a imagem abaixo:

Existem mais recursos interessantes, que estão documentados no link para baixar o Plugin.
terça-feira, 13 de setembro de 2011
>> CRM 2011 - Busca de Dados do CRM via JScript-JQuery
Segue os procedimentos para utilizar este poderoso recurso do CRM 2011:
1 - Baixar o SDK do produto;
2 - Após extrair o SDK em qualquer diretório, ir até o sub-diretório [sdk\samplecode\js\restendpoint\jqueryrestdataoperations\jqueryrestdataoperations\scripts] e importar o arquivo [jquery1.4.1.min.js] como um [Web Resource] no CRM;
3 - Efetuar o mesmo procedimento do passo 2, para o arquivo [jqueryrestdataoperationfunctions.js];
4 - Ao associar estes Web Resources a entidade do CRM desejada, atente para a ordem, pois é relevante no carregamento da página:
4.1 - primeiro [jquery1.4.1.min.js];
4.2 - depois [jqueryrestdataoperationfunctions.js];
4.3 - por último, seu próprio JS, que utilizará os recursos acima.
P.S.: Apenas para lembrar o caminho, para efetuar o passo 4, abrir o formulário da entidade desejada e clicar no botão [Propriedades do Formulário], como exemplifica a tela abaixo:

5- No sub-diretório citado no passo 2, existe uma arquivo chamado [jqueryrestdataoperationactions.js] que contém diversos exemplos de uso. Segue abaixo um deles:
function retrieveAccount(id) {
// [retrieveRecord] está presente na biblioteca [jqueryrestdataoperationfunctions.js].
retrieveRecord(id, "AccountSet", retrieveAccountCompleted, null);
}
function retrieveAccountCompleted(data, textStatus, XmlHttpRequest) {
alert(data.Name);
}
Para trabalhar com buscas mais complexas, existe a função [retrieveMultiple]. Porém, infelizmente, não existe exemplo no SDK. Consegui achar um artigo muito bom chamado [Adding Selection Criteria to REST Queries in CRM 2011]. Testei um caso com sucesso. Vale realmente a pena checar.
1 - Baixar o SDK do produto;
2 - Após extrair o SDK em qualquer diretório, ir até o sub-diretório [sdk\samplecode\js\restendpoint\jqueryrestdataoperations\jqueryrestdataoperations\scripts] e importar o arquivo [jquery1.4.1.min.js] como um [Web Resource] no CRM;
3 - Efetuar o mesmo procedimento do passo 2, para o arquivo [jqueryrestdataoperationfunctions.js];
4 - Ao associar estes Web Resources a entidade do CRM desejada, atente para a ordem, pois é relevante no carregamento da página:
4.1 - primeiro [jquery1.4.1.min.js];
4.2 - depois [jqueryrestdataoperationfunctions.js];
4.3 - por último, seu próprio JS, que utilizará os recursos acima.
P.S.: Apenas para lembrar o caminho, para efetuar o passo 4, abrir o formulário da entidade desejada e clicar no botão [Propriedades do Formulário], como exemplifica a tela abaixo:

5- No sub-diretório citado no passo 2, existe uma arquivo chamado [jqueryrestdataoperationactions.js] que contém diversos exemplos de uso. Segue abaixo um deles:
function retrieveAccount(id) {
// [retrieveRecord] está presente na biblioteca [jqueryrestdataoperationfunctions.js].
retrieveRecord(id, "AccountSet", retrieveAccountCompleted, null);
}
function retrieveAccountCompleted(data, textStatus, XmlHttpRequest) {
alert(data.Name);
}
Para trabalhar com buscas mais complexas, existe a função [retrieveMultiple]. Porém, infelizmente, não existe exemplo no SDK. Consegui achar um artigo muito bom chamado [Adding Selection Criteria to REST Queries in CRM 2011]. Testei um caso com sucesso. Vale realmente a pena checar.
>> CRM 4.0 - FetchXML via JScript
Segue código aprimorado (extraído do SDK - http://technet.microsoft.com/en-us/library/cc677073.aspx) para busca de qualquer informação do CRM, via JScript.
window.ExecFetchXML = function (entityName, column, conditionAttribute, operator, value, fieldOrderName, fieldOrderValue, page, count) {
var fetchMapping = "logical";
var filterType = "and";
var authenticationHeader = GenerateAuthenticationHeader();
var columnSplit = column.split(",");
var conditionAttributeSplit = conditionAttribute.split(",");
var operatorSplit = operator.split(",");
var valueSplit = value.split(",");
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'>" +
authenticationHeader +
"<soap:Body>" +
"<Fetch xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>" +
"<fetchXml><fetch mapping='" + fetchMapping + "'";
if (page != null) xml += " page='" + page + "' ";
if (count != null) xml += " count='" + count + "' ";
xml += "><entity name='" + entityName + "'>";
if (columnSplit.length > 1) {
for (i = 0; i < columnSplit.length; i++) {
xml += "<attribute name='" + String(columnSplit[i]) + "'/>";
}
}
else {
xml += "<attribute name='" + column + "'/>";
}
if (fieldOrderName != null && fieldOrderValue != null) {
xml += "<order attribute='" + fieldOrderName +
"' descending='" + fieldOrderValue + "'/>";
}
if (conditionAttribute != null && operator != null && value != null) {
xml += "<filter type='" + filterType + "'>";
if (conditionAttributeSplit.length > 1) {
for (i = 0; i < conditionAttributeSplit.length; i++) {
xml += "<condition attribute='" + conditionAttributeSplit[i] + "'" +
" operator='" + operatorSplit[i] + "' value='" + valueSplit[i] + "'/>";
}
}
else {
xml += "<condition attribute='" + conditionAttribute + "'" +
" operator='" + operator + "' value='" + value + "'/>";
}
xml += "</filter>";
}
xml += "</entity>" +
"</fetch></fetchXml>" +
"</Fetch>" +
"</soap:Body>" +
"</soap:Envelope>";
// Prepare the xmlHttpObject and send the request.
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xHReq.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Fetch");
xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);
// Capture the result.
var resultXml = xHReq.responseXML;
// Check for errors.
var errorCount = resultXml.selectNodes('//error').length;
if (errorCount == 0) {
// Capture the result and UnEncode it.
var resultSet = new String();
resultSet = resultXml.text;
resultSet = resultSet.replace("<resultset morerecords=\"0\" />", "");
if (resultSet != "") {
// Create an XML document that you can parse.
var oXmlDoc = new ActiveXObject("Microsoft.XMLDOM");
oXmlDoc.async = false;
// Load the XML document that has the UnEncoded results.
oXmlDoc.loadXML(resultSet);
var retValue = null;
if (oXmlDoc.getElementsByTagName('result') != null) {
var objLen = oXmlDoc.getElementsByTagName('result').length;
retValue = new Array(objLen);
// Loop nas Linhas
for (j = 0; j < objLen; j++) {
retValue[j] = new Object();
if (columnSplit.length > 1) {
for (i = 0; i < columnSplit.length; i++) {
if (oXmlDoc.getElementsByTagName('result')[j].selectSingleNode(String(columnSplit[i])))
eval("retValue[" + String(j) + "]." + String(columnSplit[i]) + "= '" + oXmlDoc.getElementsByTagName('result')[j].selectSingleNode('./' + String(columnSplit[i])).text + "'");
}
}
else {
if (oXmlDoc.getElementsByTagName('result')[j].selectSingleNode(column))
eval("retValue[" + String(j) + "]." + column + "= '" + oXmlDoc.getElementsByTagName('result')[j].selectSingleNode(column).text + "'");
}
}
}
}
}
return retValue;
}
E as formas de utilização:
var result1 = window.ExecFetchXML('account', 'accountid, name', 'name', 'like', '%TESTE%', null, null, null, null);
alert(result1[0].accountid);
alert(result1[0].name);
/*
- Ordenado por [name];
- Ascendente [true];
- Retorna 2 páginas, com 10 clientes por página.
*/
var result2 = window.ExecFetchXML('account', 'accountid, name', 'name', 'eq', 'TESTE', 'name', 'true', 2, 10);
/*
- Busca por vários campos (name like '%TESTE%' e cnpj='12345678900');
*/
var result3 = window.ExecFetchXML('account', 'accountid, name', 'name,cnpj', 'like,eq', '%TESTE%,12345678900', null, null, null, null);
window.ExecFetchXML = function (entityName, column, conditionAttribute, operator, value, fieldOrderName, fieldOrderValue, page, count) {
var fetchMapping = "logical";
var filterType = "and";
var authenticationHeader = GenerateAuthenticationHeader();
var columnSplit = column.split(",");
var conditionAttributeSplit = conditionAttribute.split(",");
var operatorSplit = operator.split(",");
var valueSplit = value.split(",");
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'>" +
authenticationHeader +
"<soap:Body>" +
"<Fetch xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>" +
"<fetchXml><fetch mapping='" + fetchMapping + "'";
if (page != null) xml += " page='" + page + "' ";
if (count != null) xml += " count='" + count + "' ";
xml += "><entity name='" + entityName + "'>";
if (columnSplit.length > 1) {
for (i = 0; i < columnSplit.length; i++) {
xml += "<attribute name='" + String(columnSplit[i]) + "'/>";
}
}
else {
xml += "<attribute name='" + column + "'/>";
}
if (fieldOrderName != null && fieldOrderValue != null) {
xml += "<order attribute='" + fieldOrderName +
"' descending='" + fieldOrderValue + "'/>";
}
if (conditionAttribute != null && operator != null && value != null) {
xml += "<filter type='" + filterType + "'>";
if (conditionAttributeSplit.length > 1) {
for (i = 0; i < conditionAttributeSplit.length; i++) {
xml += "<condition attribute='" + conditionAttributeSplit[i] + "'" +
" operator='" + operatorSplit[i] + "' value='" + valueSplit[i] + "'/>";
}
}
else {
xml += "<condition attribute='" + conditionAttribute + "'" +
" operator='" + operator + "' value='" + value + "'/>";
}
xml += "</filter>";
}
xml += "</entity>" +
"</fetch></fetchXml>" +
"</Fetch>" +
"</soap:Body>" +
"</soap:Envelope>";
// Prepare the xmlHttpObject and send the request.
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xHReq.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Fetch");
xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);
// Capture the result.
var resultXml = xHReq.responseXML;
// Check for errors.
var errorCount = resultXml.selectNodes('//error').length;
if (errorCount == 0) {
// Capture the result and UnEncode it.
var resultSet = new String();
resultSet = resultXml.text;
resultSet = resultSet.replace("<resultset morerecords=\"0\" />", "");
if (resultSet != "") {
// Create an XML document that you can parse.
var oXmlDoc = new ActiveXObject("Microsoft.XMLDOM");
oXmlDoc.async = false;
// Load the XML document that has the UnEncoded results.
oXmlDoc.loadXML(resultSet);
var retValue = null;
if (oXmlDoc.getElementsByTagName('result') != null) {
var objLen = oXmlDoc.getElementsByTagName('result').length;
retValue = new Array(objLen);
// Loop nas Linhas
for (j = 0; j < objLen; j++) {
retValue[j] = new Object();
if (columnSplit.length > 1) {
for (i = 0; i < columnSplit.length; i++) {
if (oXmlDoc.getElementsByTagName('result')[j].selectSingleNode(String(columnSplit[i])))
eval("retValue[" + String(j) + "]." + String(columnSplit[i]) + "= '" + oXmlDoc.getElementsByTagName('result')[j].selectSingleNode('./' + String(columnSplit[i])).text + "'");
}
}
else {
if (oXmlDoc.getElementsByTagName('result')[j].selectSingleNode(column))
eval("retValue[" + String(j) + "]." + column + "= '" + oXmlDoc.getElementsByTagName('result')[j].selectSingleNode(column).text + "'");
}
}
}
}
}
return retValue;
}
E as formas de utilização:
var result1 = window.ExecFetchXML('account', 'accountid, name', 'name', 'like', '%TESTE%', null, null, null, null);
alert(result1[0].accountid);
alert(result1[0].name);
/*
- Ordenado por [name];
- Ascendente [true];
- Retorna 2 páginas, com 10 clientes por página.
*/
var result2 = window.ExecFetchXML('account', 'accountid, name', 'name', 'eq', 'TESTE', 'name', 'true', 2, 10);
/*
- Busca por vários campos (name like '%TESTE%' e cnpj='12345678900');
*/
var result3 = window.ExecFetchXML('account', 'accountid, name', 'name,cnpj', 'like,eq', '%TESTE%,12345678900', null, null, null, null);
Assinar:
Comentários (Atom)


