Friday, January 25, 2008

Hiding Buttons in MSCRM 4.0

This weeks post comes from one of my co-workers. We've set up a number of solutions for clients where we hide a custom button or even the "Convert Lead" button.

If you have hidden buttons in CRM 3.0 you know that the getElementById method is used to find the Id of the button you want to hide and then you use DHTML to hide the button.

In CRM 4.0 there is some auto-incremented number or randomly generated number that gets placed at the end of all of the ElementId's on a page. Which means that the code used for CRM 3.0 will break.

The solution we found for this is to use the "title" tag, which is linked to the tooltip of your buttons. Here's the code we used to hide a custom button we wrote to map out driving directions to a client:

//Get all of the List Elements
var lis = document.getElementsByTagName('LI');

var i = 0;
//Loop through the list items
while (i < lis.length) {
//Don't worry about any list item that doesn't have the title you are looking for.
if (lis[i].getAttribute('title') == 'View directions to this account.')
{
//Replace the DHTML with blank tags to hide the button
lis[i].outerHTML='<SPAN></SPAN>'
}
i = i + 1;
}

And you're all set. Happy scripting!


If you want to hide the "Add Existing" button you can use the following script (posted by Dave Hawes):

HideAssociatedViewButtons('Account_New_Project', ['Add existing Project to this record']);

function HideAssociatedViewButtons(loadAreaId, buttonTitles){
var navElement = document.getElementById('nav_' + loadAreaId);
if (navElement != null) {
navElement.onclick = function LoadAreaOverride() {
// Call the original CRM method to launch the navigation link and create area iFrame
loadArea(loadAreaId);
HideViewButtons(document.getElementById(loadAreaId + 'Frame'), buttonTitles);
}
}
}

function HideViewButtons(Iframe, buttonTitles) {
if (Iframe != null ) {
Iframe.onreadystatechange = function HideTitledButtons() {
if (Iframe.readyState == 'complete') {
var iFrame = frames[window.event.srcElement.id];
var liElements = iFrame.document.getElementsByTagName('li');

for (var j = 0; j < buttonTitles.length; j++) {
for (var i = 0; i < liElements.length; i++) {
if (liElements[i].getAttribute('title') == buttonTitles[j]) {
liElements[i].style.display = 'none';
break;
}
}
}
}
}
}
}


David Fronk
Dynamic Methods Inc.

Monday, January 21, 2008

Word Mail Merge - a one page Quote with Line Items

Today I'm going to talk a bit about coding in Microsoft Word. If you didn't know you could do this there is a whole new world that's about to open up to you today, but if you already knew about this then hopefully I'll be showing you a thing or two that you may not have already seen.

In order to code in MSWord you have to open up the "fields" in which you can code. In a right click menu option this appears as "Toggle Fields." In order to see/access these "fields" you will need to press ALT + F9. If you open a new Word document and click ALT + F9 you won't see anything because there are no field codes on the page. You can add one however by pressing CTRL + F9.

So, a couple of key keystrokes we just learned:
ALT + F9 = Show Field Codes
CTRL + F9 = Add a new Field Code area

Once you know that you can look at all of Microsoft's templates and see what they do with Field Codes in MSWord to get their documents to look as nice as they do.

Now, the one specific point that I wanted to touch on was in regards to Quotes and line items. First just set up your document like any other form. Then when you get to the point in which you want to put the line items, you will need to insert a Field Code. This field code will check one of the parameters in the row of data, if the condition is met then it will insert the data from the row. If it does not it will move on to the next row and check it. Typically I like to check the Quantity field. If the Quantity is greater than 0 then they must be ordering it, so it must need to be on the quote.

So, your Field Code will look something like:

{ if {MERGEFIELD "Quote_Quantity"} > 0 "

< INSERT TABLE/DATA HERE >
"
}

We're almost done. We need to put an ending check on our document to make sure we don't print out the closing piece of our document over and over again, once for each line item on the quote. The key here is to check to see if the line item is the last item in the list.

It should look something like this:

{ if {MERGEFIELD "LastItem" } = "1" "

< CLOSING STATEMENTS/COMMENTS HERE >
"
}

Run through the mail merge and you should have documents that look similar to this:







Happy MSWord coding!



David Fronk
Dynamic Methods Inc.

Friday, January 11, 2008

Reports not fully working after upgrading to CRM 4.0

One of my co-workers was upgrading a system and ran into a problem with the reports not having upgraded as expected with the rest of the system.

Strangely enough reports worked just fine out of CRM but not from within the SRS Management site. The problem was found when someone tried to access the SRS dashboard that we had built for them and it gave an error stating that the IReportViewer could not be loaded through the SRS.

So, the symptoms were reports "worked" in CRM but only CRM. Reports did not work outside of CRM, which broke non-CRM SRS reports as well as any dashboard that was referenced directly via URL.

With a bit of help from MSCRM support we were able to determine that the CRM web.config was being applied to the SRS pages since CRM and the Report Server web pages were all under the same website.

To fix the problem we moved the Report Server web pages (virtual directories) off of the CRM web site and onto a new web site on a different port. Once we did that and changed the pointers to the SRS virtual directories in CRM everything worked great.

Hope no one else has the same problem but if you do, there's hope.

David Fronk
Dynamic Methods Inc.

Monday, January 07, 2008

CRM 4.0 SDK now available

The MSCRM 4.0 SDK is now out and available for download.

Click here to download the SDK from Microsoft.

Happy coding!

David Fronk
Dynamic Methods Inc.

Saturday, January 05, 2008

Adding Notes or Activities to Existing Entities and Copying Entities

Sonoma Partners posted a great article about Enabling Mail Merge for Upgraded Custom Entities where they export an entity, look at the XML, modify one of the tags, and then reimport the XML. Until their post I had not seen this new XML tag so I was very excited to see this great find because I was actually pretty disappointed about what I could and couldn't use with Mail Merge.

My post today builds on this a little and I'll show you another use for looking at exported entity XML.

I once made a custom entity with literally 150+ fields under the assumption that no activities or notes would be needed on the custom entity. During a screen review I was told everything looked great but they wanted to attach things to the entity...and I then thought about recreating all 150+ fields, placing them on the form, and applying the scripts...again. I was not excited about doing that at all because as you may or may not know, once you create an entity and set it up with or without Notes and Activities, it's set, there's no checkbox to click to get that functionality added back after creation.

After a bit of searching and a random idea about reimporting my XML into an existing entity I found my answer. I exported the entity XML hoping to import it on top of an existing custom entity that had Notes and Activities enabled, I got an error however regarding type codes not matching or already existing. So, I went through the XML and as I was searching I found some tags (that you can see very apparently in one of the Sonoma screenshots of their post) called:

HasRelatedNotes
HasRelatedActivities

I then had a crazy idea. I deleted my old entity, published, changed the HasRelatedNotes tag to True (or 1), imported the "new" entity and I then had all 150+ fields, form setup and scripts as before only this time with attachment capabilities.

Now take this one step further and you could even copy an entity by modifying a few tags here and there so that the "copied" entity has a unique name, entitytypecode, and identifiers. I've done this a couple of times and I have to fight errors about things already existing but for the most part the errors were decent in letting me know what I has messed up...not necessarily where though. It's great for larger custom entities that need to be extremely similar. I don't come across this all that often, but it has come up and has saved me hours of time for my clients.

Maybe not the most user-friendly way of doing things but it is much faster and not nearly as tedious as reentering hundreds of fields and hoping you get all of the types, max vaules and defaults correct a second time.

Hope this helps someone else who could be in dire needs of a quick solution to a similar problem that I ran into.

David Fronk
Dynamic Methods Inc.