Monday, January 31, 2011

Dare to be GREAT! http://www.bizforward.cws-international.com/2011/01/31/dare-to-be-great/

Sunday, January 30, 2011

Contest: http://www.bizforward.cws-international.com/contests/ Good luck :)

Important! you can be one of us! Join the best team... one click away! http://www.bizforward.cws-international.com/we-recruit/

Saturday, January 29, 2011

Website launched

Our website just launched. Please check it out: http://biz-forward.com . Thanks

Format date fields in CRM

Special thanks to Andriy a33ik Butenko for this post.

// Formats the date into a certain format
Date.prototype.Format = function(format)
{
var d = this;
var f = "";
f = f + format.replace( /dd|mm|yyyy|MM|hh|ss|ms|APM|\s|\/|\-|,|\./ig ,
function match()
{
switch(arguments[0])
{
case "dd":
var dd = d.getDate();
return (dd <>
case "mm":
var mm = d.getMonth() + 1;
return (mm <>
case "yyyy": return d.getFullYear();
case "hh":
var hh = d.getHours();
return (hh <>
case "MM":
var MM = d.getMinutes();
return (MM <>
case "ss":
var ss = d.getSeconds();
return (ss <>
case "ms": return d.getMilliseconds();
case "APM":
var apm = d.getHours();
return (apm <>
default: return arguments[0];
}
});

return f;
}

// Formats the date to CRM format
Date.prototype.toCRMFormat = function()
{
var d = this;
var f = d.Format("yyyy-mm-ddThh:MM:ss+" + (-d.getTimezoneOffset()/60) + ":00");

return f;
}

Friday, January 28, 2011

Authors

Our crew just got bigger. Let's welcome our newest authors. Here's a brief description about each author.

Mirel APOSTOL - Tech Mastermind
- he got his title for a good reason, he's the most skilled developer/architect I met so far. There's no technology he can't master or teach others. But his skills go beyong programming, Mirel being a good manager/leader. He proved himself in each and every project he was a part of. He has a good sense of humour, enthusiasm and he is the man you need on your side, if you want to get your business forward :) Let's all welcome Mirel.

Octavian CUCUTA - Software Developer
- and a very good friend of mine. Tavi is the developer that thinks in general terms and the code he writes can serve more than just the problem it was written for. Design is also one of his skills. Tavi puts passion in every single line of code he writes, he documents his job very well and, to be honest, am glad I can collaborate with him. Let's welcome Tavi.

Walter HAUPTMANN - Business Consultant
- my friend, my neighbour, my colleague, my managing partner @ CWS. Walter started as a developer and now he's a very skilled business analyst, consultant and project manager. He often has innovative ideas and likes to express himself via design, painting being one of his hobbies. Also, he's the funniest man I've met. In my opinion, he should consider a stand-up comedian career :) Let's welcome Walter.

Alina ANDREESCU - Software Developer
- a lovely and funny presence, very smart and skilled .NET developer. She's the type of person that treats all the tasks seriously, making the final products work smooth. Alina is a bit shy, so let's encourage her writing skill :) Let's welcome Alina.

Radu CHIRAN - Business Consultant
- he's the party-animal type. I can't imagine a good party, without him there. He's more of a dancer than human (to quote the famous song). Radu also has the vision of a product manager. He can easily track business goals & needs and analyse them, so coders can make it happen. Also, his sense of humour is one thing you'll surely notice if you get the honor to meet him in person. All my respect for him, let's welcome Radu.

Daniel PINSLER - Software Developer
- and also a very good product support professional who likes to get the job done well. If you got a question with no answer, don't worry, he has all the answers (yes boys & girls, when you have a dilemma, contact Dani). He also loves house music and house events and. Let's welcome Daniel.

Nikolay EFTIMOV - Solutions Architect
- I met Nikolay in a Microsoft vs. Oracle PoC competition. He made a real good impression. He easily masters more than just Microsoft Dynamics CRM platform. The final product he worked on for that competition was more than I personally expected. He's a skilled coder & architect and I'm sure there's no task he can't complete. Let's welcome Nikolay.

Ciprian MOCANU - Web Developer
- he's the best friend one can have. He's a very skilled web developer, leading MBE to success daily (he's "the duck behind the operation"). Let's all welcome Ciprian.

Cornel CROITORIU - Senior Software Developer & Founder
- My mission is simple. Here's why I did this: "Because I strongly believe that a good business solution is a must for every business, no matter the stage. This blog will help both developers & consultants achieve their goals, making the final product exactly what the customer wanted."

And a song I hope from all my heart that this blog will be one day, thanks to all of you - the community. Welcome to the new Biz-Forward.com!




Cornel

Areas of interest

These are the areas we will cover in our posts:

Microsoft Dynamics CRM
Microsoft Dynamics NAV
Microsoft Dynamics AX
Microsoft SharePoint
Microsoft Office
Microsoft SQL Server
C#
WPF
WCF
Silverlight
ASP
HTML
JavaScript
.NET Framework
Windows 7
Windows Mobile
Windows Phone 7
Visual Studio 2010
Microsoft Surface
Project Management
Product Management
PR
Marketing

Rebranding

Our blog will "suffer" some minor adjustments. It won't be just a CRM blog from now on, but a Microsoft Business Solutions blog, with topics about Dynamics CRM, NAV, AX, SharePoint, Office, .NET (C#, WPF, WCF, Silverlight, asp), HTML & JavaScript and much more. Stay tuned, we are gonna move your business process forward, for our new name/brand is Biz Forward.

Thursday, January 27, 2011

Change attachment file limit

More details about this issue can be found here: http://rahulsalunkhe.wordpress.com/2010/08/26/increasing-the-crm-4-0-attachment-size-limit . This should work under CRM 2011 as well.

Wednesday, January 26, 2011

CRM Usage Report

A very nice thread about this issue, written by David Jennaway - MVP, can be found here.

Generate a new Guid in JavaScript

As easy as that :)

// Generate new Guid

function Hexa4()
{
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}
function GenerateGuid()
{
return (Hexa4()+Hexa4()+"-"+Hexa4()+"-"+Hexa4()+"-"+Hexa4()+"-"+Hexa4()+Hexa4()+Hexa4()).toUpperCase();
}

// USE
var guid = GenerateGuid();
alert(guid);

Create a custom filtered lookup view in runtime - CRM 2011

Starting CRM 2011 you can filter a certain lookup view based on related entities or other system/custom views. But sometimes this is not enough. For example, if you wanna make a custom filtered view, that uses several filters, you can use the following approach.

Starting scenario (all of the completed lookup fields will be used as filters):


// *** ALL IN 1 CODE ***
// Structs
var FilterBy = MakeStruct("SchemaName Operator Value");
var ViewColumn = MakeStruct("SchemaName Width");

// Advanced Filtered Lookup
function AdvancedFilteredLookup(lookupSchemaName, viewId, entityName, primaryKeyName, primaryFieldName, viewDisplayName, filterBy, orderBy, viewColumns)
{
var fetchXml = "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>" +
"<entity name='" + entityName + "'>" +
"<attribute name='" + primaryFieldName + "' />" +
"<order attribute='" + orderBy + "' descending='false' />" +
"<filter type='and'>" +
"<filter type='and'>";
for(var i=0; i< filterBy.length; i++)
fetchXml += "<condition attribute='" + filterBy[i].SchemaName + "' operator='" + filterBy[i].Operator + "' value='" + filterBy[i].Value + "' />";
fetchXml += "</filter></filter></entity></fetch>";

var layoutXml = "<grid name='resultset' " +
"object='1' " +
"jump='name' " +
"select='1' " +
"icon='1' " +
"preview='1'>" +
"<row name='result' " +
"id='" + primaryKeyName + "'>";
for(var i=0; i< viewColumns.length; i++)
layoutXml += "<cell name='" + viewColumns[i].SchemaName + "' width='" + viewColumns[i].Width.toString() + "' />";
layoutXml += "</row></grid>";

try {
var lookupControl = Xrm.Page.ui.controls.get(lookupSchemaName);
lookupControl.addCustomView(viewId, entityName, viewDisplayName, fetchXml, layoutXml, true);
}
catch(err) {
}
}

// USE - we gonna create a custom filtered lookup view for the new_productid lookup field
// Note: this function should be called on the OnChange() event of all the filter-fields (for example: new_type1id)
function FilterProducts()
{
try {
// Parameters
var customViewId = "{FD140AAF-4DF4-11DD-BD17-0019B9312238}"; // new id
var customViewName = "Type Filtered Products";
var lookupFieldName = "new_productid";
var entityName = "product";
var primaryKeyName = "productid";
var primaryFieldName = "name";
var orderBy = "name";

// Generate Filters
var type1id = crmForm.all.item("nov_type1id").DataValue != null ? crmForm.all.item("nov_type1id").DataValue[0].id : null;
var type2id = crmForm.all.item("nov_type2id").DataValue != null ? crmForm.all.item("nov_type2id").DataValue[0].id : null;
var type3id = crmForm.all.item("nov_type3id").DataValue != null ? crmForm.all.item("nov_type3id").DataValue[0].id : null;
var type4id = crmForm.all.item("nov_type4id").DataValue != null ? crmForm.all.item("nov_type4id").DataValue[0].id : null;
var clientneedid = crmForm.all.item("nov_clientneedid").DataValue != null ? crmForm.all.item("nov_clientneedid").DataValue[0].id : null;
var vendorid = crmForm.all.item("nov_vendorid").DataValue != null ? crmForm.all.item("nov_vendorid").DataValue[0].id : null;
var filters = new Array();
var index = 0;
if(type1id != null)
filters[index++] = new FilterBy("new_type1id", LogicalOperator.Eq, type1id);
if(type2id != null)
filters[index++] = new FilterBy("new_type2id", LogicalOperator.Eq, type2id);
if(type3id != null)
filters[index++] = new FilterBy("new_type3id", LogicalOperator.Eq, type3id);
if(type4id != null)
filters[index++] = new FilterBy("new_type4id", LogicalOperator.Eq, type4id);
if(clientneedid != null)
filters[index++] = new FilterBy("new_clientneedid", LogicalOperator.Eq, clientneedid);
if(vendorid != null)
filters[index++] = new FilterBy("nov_vendorid", LogicalOperator.Eq, vendorid);

// View Columns
var viewColumns = [new ViewColumn("name", 200), new ViewColumn("productnumber", 100), new ViewColumn("new_type1id", 100), new ViewColumn("new_type2id", 100), new ViewColumn("new_type3id", 100), new ViewColumn("new_type4id", 100), new ViewColumn("new_clientneedid", 100), new ViewColumn("nov_vendorid", 100)];

// Create Dynamics View
AdvancedFilteredLookup(lookupFieldName, customViewId, entityName, primaryKeyName, primaryFieldName, customViewName, filters, orderBy, viewColumns);

// Clear Previous Product Value
crmForm.all.item(lookupFieldName).DataValue = null;
}
catch(err) {
}
}

And now, the custom filtered lookup view for the new_productid lookup field will look like this:


Hope you'll find this article useful.

P.S.: In my opinion, filtering a lookup this way is a lot more efficient than altering the lookupsingle.aspx file (the unsupported method used in CRM 4.0) ;)

Creating records in CRM 2011 using JavaScript

Using the CRM Web Service, you can create new entity records, just using JavaScript. The following code demonstrates this:

// Make Struct
function MakeStruct(names) {
var names = names.split(' ');
var count = names.length;
function constructor() {
for (var i = 0; i < count; i++) {
this[names[i]] = arguments[i];
}
}
return constructor;
}


// CRM Field Struct
var CRMField = MakeStruct("SchemaName Value");

// Call Crm Service
function CallCrmService(soapBody, method)
{
try {
var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
xmlHttpRequest.Open("POST", '/mscrmservices/2007/CrmService.asmx', false);
xmlHttpRequest.setRequestHeader("SOAPAction", 'http://schemas.microsoft.com/crm/2007/WebServices/' + method);
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
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\'>" +
GenerateAuthenticationHeader() + "<soap:Body>" + soapBody + "</soap:Body></soap:Envelope>";
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml);

var resultXml = xmlHttpRequest.responseXML;
var errorCount = resultXml.selectNodes('//error').length;

if (errorCount != 0) {
var msg = resultXml.selectSingleNode('//description').nodeTypedValue;
alert(msg);

return null;
}

return resultXml;
}
catch(err) {
}

return null;
}

// Create Record
function CreateRecord(entityName, fields)
{
try {
var resultArray = new Array();
var attributesList = '';

for(var i = 0; i < fields.length; i++)
attributesList += "<" +
fields[i].SchemaName + ">" + fields[i].Value + "</"+fields[i].SchemaName+">";
}

var xml = "
<Create xmlns='http://schemas.microsoft.com/crm/2007/WebServices'><entity xsi:type='"+entityName+"'>" + attributesList + "</entity></Create>";
var resultXml = CallCrmService(xml, 'Create');

if (resultXml) {
var newid = resultXml.selectSingleNode('//CreateResult').nodeTypedValue;
return newid;
}
}
catch(err) {
}

return null;

}

// USE
// Create new Contact
function CreateContact()
{
var fields = [new CRMField('firstname', 'Cornel'), new CRMField('lastname, 'Croitoriu')];
return CreateRecord('contact', fields); // return new contact id
}

// Create new Annotation
function CreateAnnotation(parentEntityName, parentEntityId, title, text)
{
var fields = [new CRMField('objecttypecode', parentEntityName), new CRMField('objectid', parentEntityId), new CRMField('subject', title), new CRMField('notetext', text), new CRMField('isdocument', false), new CRMField("mimetype", "text/html")];
return CreateRecord('annotation', fields); // return new note id
}

// Example
CreateAnnotation('opportunity', 'FD140AAF-4DF4-11DD-BD17-0019B9312238', 'dynamic generated note', 'text goes here...');

Microsoft Dynamics CRM 2011 Online Global Availability

Microsoft Dynamics CRM 2011 goes international: 40 countries, 41 languages. Click here for more details.

Set a lookup value in CRM 2011

// Sets the lookup value for a certain field
function SetLookupValue(fieldName, id, name, entityType) {
if(fieldName != null) {
var lookupValue = new Array();
lookupValue[0] = new Object();
lookupValue[0].id = id;
lookupValue[0].name = name;
lookupValue[0].entityType = entityType;

Xrm.Page.getAttribute(fieldName).setValue(lookupValue);
}
}

// USE
SetLookupValue("new_blogid", "{FD140AAF-4DF4-11DD-BD17-0019B9312238}", "CRM Stuff", "new_blog");

JavaScript structures

Here's a brief example of how to create structures in JavaScript. We'll use this function a lot from now on in our code.

// Make Struct
function MakeStruct(names) {
var names = names.split(' ');
var count = names.length;
function constructor() {
for (var i = 0; i < count; i++) {
this[names[i]] = arguments[i];
}
}
return constructor;
}

// Use
// Declaring the struct
var Person = MakeStruct("ID FirstName LastName Email");
// Instance
var person1 = new Person(21, "Cornel", "Croitoriu", "cscmediadesign@yahoo.com");

Hope you'll find this useful ;)

Tuesday, January 25, 2011

CRM Stuff - 4 years together

CRM Stuff has reached its 4th anniversary. I'd like to thank the community for all the support, comments, ideas, suggestions and thoughts.

Best of luck,
Cornel
CRM Stuff

CRM 2011 Custom Form Button



Using some of the basic DOM vs JavaScript capabilities, you can use the following code to dynamically generate a custom button for your CRM Form in Microsoft Dynamics CRM 2011 (scroll to the end of this post to see an example of how to use it). The button will look just like the ones in the toolbar.
All you need is a random CRM field (the type doesn't matter) to host the button (the original field content will be hidden). Also, you'll need a custom function to pass for the onclick event.
Note: the image you use for the button must be placed inside the %programfiles%\Microsoft Dynamics CRM\CRMWeb\_imgs\ico folder.

The final output looks like this:




And... here's the code masterpiece :)...

// CODE

// Create Dynamic Button for CRM 5
function CreateButtonCRM5(fieldName, buttonText, buttonWidth, iconName, clickEvent)
{
functiontocall=clickEvent;
crmForm.all.item(fieldName + "_c").style.display = "none";

var li = document.createElement("LI");
li.setAttribute('id', fieldName + 'LI');
li.setAttribute('className', 'ms-crm-Menu');
li.setAttribute('title', buttonText);
li.setAttribute('onclick', functiontocall);
li.setAttribute('onmousedown', push_custom_button);
li.setAttribute('onmouseup', release_custom_button);
li.style.width=buttonWidth;
li.style.cursor="hand";
li.style.textAlign="center";
li.style.overflow="hidden";

var span = document.createElement("span");
span.setAttribute('className', 'ms-crm-Menu-Label');
span.setAttribute('id', fieldName + 'Span');
span.style.cursor = "hand";
li.appendChild(span);
li.onmouseover = function() { span.setAttribute('className', 'ms-crm-Menu-Label-Hovered'); }
li.onmouseout = function() { span.setAttribute('className', 'ms-crm-Menu-Label'); }

var a = document.createElement("a");
a.setAttribute('id', fieldName + 'A');
a.setAttribute('className', 'ms-crm-Menu-Label');
a.onclick = function() { return false; }
a.setAttribute('target', '_self');
a.setAttribute('href', 'javascript:onclick();');
a.style.cursor = "hand";
span.appendChild(a);

var img = document.createElement("img");
img.setAttribute('id', fieldName + 'Img');
img.setAttribute('className', 'ms-crm-Menu-ButtonFirst');
img.setAttribute('src', '/_imgs/ico/' + iconName);
img.style.cursor = "hand";

var span2 = document.createElement("span");
span2.setAttribute('id', fieldName + 'Span2');
span2.setAttribute('className', 'ms-crm-MenuItem-TextRTL');
span2.innerText = buttonText;
span2.style.cursor = "hand";
a.appendChild(img);
a.appendChild(span2);

removeChildNodes(crmForm.all.item(fieldName + "_d"));
crmForm.all.item(fieldName + "_d").appendChild(li);
}

function push_custom_button()
{
window.event.srcElement.style.marginLeft="1px";
window.event.srcElement.style.marginTop="1px";
}

function release_custom_button()
{
window.event.srcElement.style.marginLeft="0px";
window.event.srcElement.style.marginTop="0px";
}

// USE
function CustomClickFunction()
{
alert("your code goes here...");
}

// Create the button, using the new_custombutton field as a container
CreateButtonCRM5('new_custombutton', 'Custom Button','100 px', '16_cancel.png', CustomClickFunction);


BONUS:
For the developers out there who are still using CRM 4.0, you can use the following function to generate a custom button, CRM styled, based on the same principles as previous article/function.

// Create Dynamic Button for CRM 4
function CreateButtonCRM4(fieldName, buttonText, buttonWidth, clickEvent)
{
functiontocall=clickEvent;
crmForm.all.item(fieldName + "_c").style.display = "none";

crmForm.all.item(fieldName).DataValue = buttonText;
crmForm.all.item(fieldName).style.borderRight="#3366cc 1px solid";
crmForm.all.item(fieldName).style.paddingRight="5px";
crmForm.all.item(fieldName).style.borderTop="#3366cc 1px solid";
crmForm.all.item(fieldName).style.paddingLeft="5px";
crmForm.all.item(fieldName).style.fontSize="11px";
crmForm.all.item(fieldName).style.backgroundImage="url(/_imgs/btn_rest.gif)";
crmForm.all.item(fieldName).style.borderLeft="#3366cc 1px solid";
crmForm.all.item(fieldName).style.width=buttonWidth;
crmForm.all.item(fieldName).style.cursor="hand";
crmForm.all.item(fieldName).style.lineHeight="18px";
crmForm.all.item(fieldName).style.borderBottom="#3366cc 1px solid";
crmForm.all.item(fieldName).style.backgroundRepeat="repeat-x";
crmForm.all.item(fieldName).style.fontFamily="Tahoma";
crmForm.all.item(fieldName).style.height="20px";
crmForm.all.item(fieldName).style.backgroundColor="#cee7ff";
crmForm.all.item(fieldName).style.textAlign="center";
crmForm.all.item(fieldName).style.overflow="hidden";
crmForm.all.item(fieldName).attachEvent("onmousedown",push_custom_button);
crmForm.all.item(fieldName).attachEvent("onmouseup",release_custom_button);
crmForm.all.item(fieldName).attachEvent("onclick",functiontocall);
crmForm.all.item(fieldName).contentEditable= false;
}


and the output: