-
Free Utility Released: Export JavaScript from CRM
Part of an upcoming commercial utility I am building exports custom JavaScript found in a CRM installation. I needed that functionality for a current customer project so I decided to go ahead and create a separate utility that performs that one function.
Here is the user interface:
JavaScript Extraction Rules
The JavaScript found within each entity will be extracted using the following rules:
- Only custom JavaScript is extracted. Built-in CRM JavaScript is ignored.
- JavaScript for the Form’s OnLoad and OnSave events will be exported.
- JavaScript for each Atttribute’s OnChange event will be exported.
- Only active JavaScript is exported. If you don’t have the Active checkbox on the event checked, it is ignored.
- If the JavaScript is Active but there is no JavaScript in the event, it is ignored.
Output Folder
A sub-folder will be created using the name of the CRM Organization in the folder where the utility is located.
Output Contents
Each event will be written to a separate file with a .js extension. The naming convention is:
OnLoad
<entity>_onload.js
OnChange
<entity>_<attribute>_onchange.js
Here is what the new Demo CRM VPC installation’s output looks like:
Download it from the Free Utilities page.
Customization, Dynamics CRM 1,199 views -
Free CRM utilities moved to this blog
I moved my free CRM utilities to this site today. They mostly work with CRM 3.0 but I plan to update a couple of them soon to support 4.0.
Check out the following page:
Dynamics CRM 542 views -
Do you use CardScan for CRM?
I have added a new poll to this blog because I’m curious about how many people actually use the CardScan for MSCRM product.
Dynamics CRM 618 views -
Working with Currencies, Revisited
In a previous article, I reviewed an error I was receiving when performing some JavaScript calculations on a CRM form. I ran into the same error message this week, but under different circumstances.
The user was receiving the following error message when opening a record of a custom entity we created:
Hmm, I thought to myself, I’ve seen this before.
It turns out that I was creating this record via a plug-in and had forgotten to include the transactioncurrencyid in the record.
Remember: You must always include the transactioncurrencyid attribute on any record you create if there is a money attribute contained anywhere within the entity.
How do you know you have a problem with the record? Instead of your money fields looking like this:
They look like this:
Notice the lack of a currency symbol to the left of the edit box?
The only way to correct such a record is to add the transactioncurrencyid attribute to the form and change the value on the form, and either use JavaScript to add the currency or have the user set it manually.
Again, the above statement applies to records that have been created programmatically. Records created manually should have the transactioncurrencyid populated automatically.
So, to keep from having issues, just add the transactioncurrencyid attribute to your list of attributes that are created.
Here is a method in C# that will pull back the information for the US Dollar:
public static transactioncurrency GetCurrency(ICrmService crmService) { // Build a query for US Dollar currency. QueryByAttribute dollarQuery = new QueryByAttribute(); dollarQuery.EntityName = EntityName.transactioncurrency.ToString(); dollarQuery.Attributes = new string[] { "currencyname" }; dollarQuery.Values = new string[] { "US Dollar" }; dollarQuery.ColumnSet = new AllColumns(); // Create the US currency request. RetrieveMultipleRequest dollarRequest = new RetrieveMultipleRequest(); dollarRequest.Query = dollarQuery; RetrieveMultipleResponse dollarResponse = (RetrieveMultipleResponse)crmService.Execute(dollarRequest); return (transactioncurrency)dollarResponse.BusinessEntityCollection.BusinessEntities[0]; }
which is used like this:
transactioncurrency usCurrency = GetCurrency(crmService); myEntity["transactioncurrencyid"] = new Lookup(EntityName.transactioncurrency.ToString(), usCurrency.transactioncurrencyid.Value);
The above assumes you’re working with Dynamic Entities inside the CRM plug-in framework.
Misc 490 views -
The Dangers of Repurposing Existing CRM Entities
Since Dynamics CRM can be so easily customized, one of the traps that CRM developers and architects occasionally find themselves in is using an existing CRM entity for a different purpose.
An example would be using the Case Entity (incident) to track product fulfillment requests.
Usually, when such a decision is made, the entity being repurposed is not being used and as far as the designers can see, it will never be used. So, they customize it to fit their needs and, in some cases, completely altering the visual and structural layout of the entity to where you can’t actually determine how it looked and worked before.
Then, as is more the case than not, 6 to 12 months into the future, when Dynamics CRM is running your business, you find yet another need that can be filled by using parts of the system that were previously unused.
The only problem is, you’ve repurposed that part ( the Case Entity, for example ) and it is so customized and heavily used that it would be almost impossible to move the customizations and data to a new entity and revert the original Entity back to it’s original design and purpose.
Repurpose or Create
If you are starting down the repurposing path, you need to ask yourself why you are doing so. What is is about the Entity that makes you think:
- You will never use it
- It has some design feature that can’t be duplicated in a custom entity
There are indeed occasions where a standard CRM Entity has a feature that you can’t duplicate on a custom Entity – like the Customer data type ( can be Account OR contact ). But most of the time, you’ll spend as much time removing or hiding the existing functionality as you would have in creating a new Entity from scratch.
Sometimes even more time is spent customizing the standard Entity and it would be to just create the whole thing from scratch.
Conclusion
When your requirements call for a new custom Entity, start from scratch, don’t automatically look for an existing Entity that is not used and change it. Microsoft spent a lot of time and effort into the design of Dynamics CRM and the relationships between the Entities is pretty well defined and understood.
Have your design add value to CRM, not change CRM in ways that will cause issues later.
Customization, Dynamics CRM 676 views -
JavaScript: Working with Dates Returned from Web Service Calls
Revised Thursday, July 11th.
I’ve been doing a lot of work recently using JavaScript to retrieve data from CRM via web service calls. One of the issues I ran into is the date format returned by CRM is in Coordinated Universal Time ( UTC ) which is not the same format most programming languages use. This leads to conversion issues or programming exceptions.
To work around any issues, I created a JavaScript function that allows me to parse the UTC date and time string and return a JavaScript Date value.
At this point, the function is only concerned with the date, but if you need the time, you can modify the function to add those additional parameters to the new Date() line.
For more information on the JavaScript Date object, please visit the following link.
function ConvertDateFromUTC(startDate){// UTC time formatted string//2009-03-25T09:30:00-00:00 // 1 2 //1234567890123456789012345var year = parseInt(startDate.substr(0, 4),10);var month = parseInt(startDate.substr(5, 2),10);var day = parseInt(startDate.substr(8, 2),10);var hour = parseInt(startDate.substr(11, 2),10);var min = parseInt(startDate.substr(14, 2),10);return new Date(year, month - 1, day);
}
July 11th: Corrected issues as pointed out by Moti, in the comments.
Making It Work
In this example, I’m using the excellent CrmService library released by Ascentium, to retrieve values from a contact.
var oService = new Ascentium_CrmService();
var asCols = ["fullname",
"address1_postalcode","address1_city","address1_stateorprovince","birthdate"];var beRetrievedContact =oService.Retrieve("contact",crmForm.all.customerid.DataValue[0].id,
asCols);
var birthDateString = beRetrievedContact.attributes["birthdate"].value;
var birthDate = new Date(ConvertDateFromUTC(birthDateString));
Customization, Dynamics CRM 1,210 views -
What keeps your people from selling?
This is one of the primary questions I ask when starting the discovery phase of a CRM implementation.
Why is this important?
This question is important to everyone because the more distractions that can be eliminated from the life of a sales person, the more time they have to sell. Hopefully, the following equation fits into your organization:
And more sales generally translates into more money – for everyone.
How do I make a difference?
During your discovery process, ask these simple questions:
- What types of reports are your sales people required to produce?
- Is any data collected and returned to anyone in an Excel worksheet?
- What procedures or processes do your salespeople perform repetitively?
Collect these answers, then review the native capabilities found with Dynamics CRM. Implement out of the box solutions when you can and create custom solutions when you must.
Your changes don’t need to occur all at once, and as always, keep the users involved in the process so they can see where you’re going and how the changes will help them sell.
Dynamics CRM 587 views -
Retrieving State and Status Options via the MetadataService
As you probably know, the State and Status options for a CRM entity are linked together. You can’t change the State options or values but you can change the Status options ( which are generally shown in a picklist ).
On a recent project, I needed to simulate the Cancel Opportunity dialog through a custom user interface. Rather than build a hard-coded list of reasons for the cancelation, I decided to use the CRM MetadataService to dynamically pull the data using the following method ( in C# ):
public SortedList RetrieveStatusList( string entityName, int statusValue) { SortedList list = new SortedList(); AttributeMetadata attMetaData; RetrieveAttributeRequest request = new RetrieveAttributeRequest(); request.EntityLogicalName = entityName; request.LogicalName = "statuscode"; RetrieveAttributeResponse response; response = (RetrieveAttributeResponse)metadataService.Execute(request); attMetaData = response.AttributeMetadata; StatusAttributeMetadata status = (StatusAttributeMetadata)attMetaData; foreach (StatusOption o in status.Options) { if (o.State.Value == statusValue) { list.Add(o.Label.UserLocLabel.Label, o.Value.Value.ToString()); } } return list; }
The method takes two parameters:
- The entity name
- The state code value
I am using this method to populate a ASP.NET dropdown list box using the following code:
DropDownList1.DataSource = RetrieveStatusList("opportunity", 2); DropDownList1.DataTextField = "Key"; DropDownList1.DataValueField = "Value"; DropDownList1.DataBind();
In the case of the Opportunity, we have the following State code values:
Name Value Lost 2 Open 0 Won 1 Since we are canceling an Opportunity, we use the Lost state, which has a value of 2.
How This Works
The key to making sense of this process is the StatusOption object. It contains data for both the Status Reason codes and the State with which are they associated.
Since we are looking for a specific state, we check the State for the Option and if it matches our expected value, we add it to the list.
Customization, Development, Dynamics CRM 732 views





