06 January 2008

Microsoft Dynamics CRM 4.0 SDK Released!

Microsoft Dynamics CRM 4.0 SDK

This package contains the complete software development kit for Microsoft Dynamics CRM 4.0.


Microsoft Dynamics CRM 4.0 Language Pack Readme

This document provides important late-breaking information.


Microsoft Dynamics CRM 4.0: Planning and Deployment Guidance for Service Providers

These guides and tool provide additional information for Service Providers to plan and deploy Microsoft Dynamics CRM 4.0.


Microsoft Dynamics CRM 4.0

Microsoft Dynamics CRM 4.0 for released languages.


Microsoft Dynamics CRM 4.0 Data Migration Manager

Using the Microsoft Dynamics CRM 4.0 Data Migration Manager, you can convert and upload data from another CRM system to Microsoft Dynamics CRM 4.0.


Microsoft Dynamics CRM 4.0 Trial Versions

Microsoft Dynamics CRM 4.0 90-day trial versions for released languages.


Microsoft Dynamics CRM for Outlook (For On-Premise and Hosted Editions)

Install Microsoft Dynamics CRM 4.0 for Outlook and Microsoft Dynamics CRM 4.0 for Outlook with Offline Access. For on-premise and hosted editions of Microsoft Dynamics CRM 4.0 only.


Microsoft Dynamics CRM 4.0 E-mail Router (On-Premise and Hosted Editions)

The E-mail Router is an interface between the Microsoft Dynamics CRM system and an e-mail system.


Examples of how to configure the Microsoft Dynamics CRM 4.0 on-premise E-mail Router in different deployment scenarios

This document lists steps to configure Microsoft Dynamics CRM 4.0 e-mail in different deployment scenarios.


Microsoft Dynamics CRM 4.0 for Outlook Readme (On-Premise and Hosted Editions)

This document provides important late-breaking information.


Microsoft Dynamics CRM 4.0 Implementation Guide

This guide contains comprehensive information about how to plan, install, and maintain Microsoft Dynamics CRM 4.0.


Microsoft Dynamics CRM 4.0 Server Readme

This document provides important late-breaking information for Microsoft Dynamics CRM 4.0 Server.


Microsoft Dynamics CRM 4.0 E-mail Router Readme (On Premise)

This document provides important late-breaking information for the Microsoft Dynamics CRM 4.0 E-mail Router (on-premise and hosted editions).


Microsoft Dynamics CRM 4.0 Data Migration Manager Readme

This document provides important late-breaking information.


Microsoft Dynamics CRM 4.0 Internet Facing Deployment Scenarios

This document covers how to set up the Microsoft Dynamics CRM 4.0 Web site to make it available from the Internet.

05 December 2007

How to setting focus to a Tab?

There are many discusses in CRM Forum, about how to setting focus to a Tab?
For example, I want the default tab1Tab to be the default tab when I open a record.

So if you put this code in onLoad() event:

document.getElementById('tab1Tab').focus();

It doesn't work as you expected.

But, if you use:

crmForm.all.tab1Tab.click();

It will work like a dream. :)

28 November 2007

How to change the width of Queue Title column?

QueueItem and its Views are not customizable in CRM v3.0, one requirement was make the Title column wider then users can see more information. (The Title column contains subject of activities/cases)
By default, Title column width = 300px, so how to change it to 500px? Here's my soluiton:

/*
../workplace/home_workplace.aspx
Make the queue title column width = 500px
*/

//1. Edit CRMWeb/workplace/home_workplace.aspx, add a new JavaScript function call: titleWidth()
function titleWidth()
{
var barCols = document.getElementById("crmGrid_gridBarCols");
barCols.getElementsByTagName("COL")[2].width = 500;
crmGrid.Refresh();
}

//2. Call this function from the existing nodeSelect() and window.onload().
function nodeSelect( sQueueId, sViewId, sMenuId )
{
......
titleWidth();
}

function window.onload()
{
......
titleWidth();
}

20 November 2007

Hide/remove/move/change entity level tags at runtime


/* Removing Sub-Account navigation bar at runtime */
if(document.all.navSubAct != null)
{
navSubAct.style.display = 'none';
}

/* Hiding Service Tag at runtime */
if(document.all._NA_CS != null)
{
document.all._NA_CS.style.display = 'none';
}

/* Moving Case under details group at runtime */
if((document.all.navService != null) && (document.all._NA_Info != null))
{
document.all._NA_Info.appendChild(navService);
}

/* Changing group name from 'Sales' to 'Management' */
if (document.all._NA_SFA != null)
{
document.getElementById("_NA_SFA").innerHTML = document.getElementById("_NA_SFA").innerHTML.replace("Sales","Management");
}

14 November 2007

Contact Quick Find: a bug?

In my environment, I have 'fullname', 'lastname', 'firstname' as the Contact 'Quick Find Columns'.
I noticed that the 'quick find' only search contacts from the current result view, not all records(which it should do). To work around this problem, you can edit '\_common\scripts\stage.js'


crmGrid.Reset(); // add this line here

if (crmGrid.GetParameter("viewid") != SavedQuerySelector.quickFindQuery)
{
crmGrid.SetParameter("viewid", SavedQuerySelector.quickFindQuery);
crmGrid.Reset();
}
else
{
crmGrid.PageNumber = 1;
}


To test it, you must firstly delete all Temporary Internet Files on Internet Explorer Options.

11 November 2007

CRM how to hide field / label / line / section / tab


/*hide field only*/
crmForm.all.field.style.display = 'none';

/*hide field and this field's label*/
crmForm.all.field.style.display = 'none';
crmForm.all.field_c.style.display = 'none';

/*hide field and the whole line which contains this field*/
crmForm.all.field.parentElement.parentElement.style.display = 'none';

/*hide field and the section which contains this field*/
crmForm.all.field.parentElement.parentElement.parentElement.style.display = 'none';

/*hide a tab(tab number comes from 0)*/
crmForm.all.tab2Tab.style.display = 'none';

08 November 2007

How to disable / readOnly CRM fields / iframes

Sometimes we need to disable all fields in CRM, so a function could help!
Also, you don't want to diable INPUT/TEXTAREA nodes, because it will become unreadble (gray #808080) if you disable it, so I prefer to set those nodes readOnly. (only INPUT and TEXTAREA support readOnly property!)


/*
setDisabled function
1. set readOnly property for INPUT/TEXTAREA nodes
2. disable other nodes
id: element's Id
ignoreNodes: nodes can be ignored
nodesDisabled: bool, true = set disable/readonly
*/

function setDisabled(id, ignoreNodes, nodesDisabled)
{
var node, nodes;
nodes = id.getElementsByTagName('*');
if(!nodes)
return;

var i = nodes.length;
while (i--)
{
node = nodes[i];
if(node.nodeName && !(node.nodeName.toLowerCase() in ignoreNodes))
{
if((node.nodeName == "INPUT") || (node.nodeName == "TEXTAREA"))
{
node.readOnly = nodesDisabled;
}
else
{
node.disabled = nodesDisabled;
}
}
}
}

/*disable/readonly fields*/
setDisabled(document.getElementById("areaForm"), {table:'', iframe:'', div:'', form:'', col:'', colgroup:'', lable:'', span:'', tbody:'', body:'', tr:'', td:''}, true);

/*disable IFRAME*/
try
{
window.setTimeout(iframeDisabled, 3000);
}
catch(err)
{
alert("System busy, please try again later!" + err);
window.close();
}

function iframeDisabled()
{
setDisabled(document.frames("IFRAME_1").document.getElementById("mnuBar1"),{}, true);
}

05 November 2007

Microsoft CRM: Filter On: Last 30 days

I have been asked how to change the default Filter On from 'Last 30 days' to 'All' in History associated view.

Micrsoft CRM doesn't provide this customisation, and there are no good solutions on the Internet. After 3 hours research for the source, I found a simple solution:
The file you need to modify is: \CRMWeb\_controls\AppGridFilterContainer\AppGridFilterContainer.htc

Open the file by notepad, and search the string : oCallback(oCtrl);
Just add some code above it:


if(oCtrl.DataValue=="LastXDays;30")
{
oCtrl.DataValue = "All";
RefreshGridView();
}

oCallback(oCtrl);


Save and Close, that's it. Next time when you open History, you will see the change.

27 October 2007

Automatically resolve e-mail sender to selected contact emailaddress1. Part II

OK, then what's the next problem?

The next problem was: If you have a contact(senderA) in CRM, the senderA has 2 email address saved in emailaddress1 and emailaddress2 fields. If senderA send an email from ouside world into CRM by using emailaddress2, then CRM will think that is a associated email address, it's good so far. But when CRM user reply this email to senderA, CRM will always use emailaddress1 to send email! Which is not good because senderA sent this email by emailaddress2, he/she doesn't expect the reply email send into his/her another email box.

So this is the requirement: make emailaddress1 dynamically, so senderA's emailaddress1 will always keep the latest email address he/she used. Because CRM Email router doesn't fire Email Pre/Post Create callout, so I decide to use Workflow assembly to make it happen. Here's the code, you still need to update workflow.xml and set up a workflow Email.Create job.


/*
* Update contact.emailaddress1 by email sender
*
* */

public void GetEmailSender(Guid activityid, String sender)
{
CrmService service = new CrmService();
service.Credentials = System.Net.CredentialCache.DefaultCredentials;
string connectionString = "Server=_db;Database=_MSCRM;Integrated Security=SSPI";

//only select a contact(partyobjecttypecode=2) which is also a sender(participationtypemask=1)
string queryString = "SELECT partyid FROM FilteredActivityParty "
+ "WHERE(participationtypemask = 1) AND "
+ "(partyobjecttypecode = 2) AND "
+ "(activityid = '" + activityid.ToString()
+ "')";

SqlConnection connection = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand(queryString, connection);
command.Connection.Open();

try
{
SqlDataReader reader = command.ExecuteReader();
Guid cid = new Guid();

while(reader.Read())
{
cid = reader.GetGuid(0); // get FilteredActivityParty.partyid
}
if(cid.ToString() != "00000000-0000-0000-0000-000000000000")
{
contact c = new contact();
c.contactid = new Key();
c.contactid.Value = cid;
c.emailaddress1 = sender;
service.Update(c);
}
}
catch (Exception ex)
{
TextWriter log = TextWriter.Synchronized(File.AppendText(@"C:\CRM_Debug\error.txt"));
log.WriteLine(DateTime.Now);
log.WriteLine(ex.ToString());
log.WriteLine("");
log.Close();
}
finally
{
connection.Close();
}
}

20 October 2007

Automatically resolve e-mail sender to selected contact emailaddress1. Part I

We faced two problems in CRM 3.0 Email, the first problem was:
When an email(senderA@example.com) sent from outside world into CRM system, if sender's email address isn't in the system, then CRM will ask you to associate it with an existing record(only associate with a Contact record in our case). But once you select a contact, it looks associated, but it doesn't update the Contact's email field. You have to open the Contact record and manually copy the sender's email address into Contact's email field.

Regarding Microsoft KB: 922116, it is by design! Our requirement is make it automatically copy the sender's email address into the assocaited Contact.emailaddress1 field.

To achieve that, I made an unsupported change(again? :))


/*
Automatically resolve e-mail sender to selected contact emailaddress1
Microsoft KB: 922116, http://support.microsoft.com/kb/922116
\_controls\PartyList\resolve.aspx
*/

function applychanges()
{
//update cotnact emailaddress1
if((document.getElementById("crmExistingLookup").DataValue != null)
&&(document.getElementById("crmExistingLookup").DataValue[0] != null)
&&(document.getElementById("crmExistingLookup").DataValue[0].type == 2))
{
var eml = document.getElementById("txtName").value;
var cid = document.getElementById("crmExistingLookup").DataValue[0].id;
var connection = new ActiveXObject("ADODB.Connection");
var connectionString = "Provider=SQLOLEDB; Server=_db; Database=_mscrm; Integrated Security=SSPI";

connection.Open(connectionString);
var sql = "UPDATE FilteredContact SET emailaddress1='" + eml +"'WHERE contactid = '" + cid + "'" ;
rs = new ActiveXObject("ADODB.Recordset");
rs.Open(sql, connection, 1, 2);

connection.Close();

}

....

}