Mar
08

Experience of web deployment of Office 2007 templates

Together with known ways to use user and workgroup templates Windows folders, the 2007 Microsoft Office system gives a possibility to use templates located on web sources. It is combined with the tools to customize the New Document dialog box for Word, PowerPoint and Excel.

The source http://technet.microsoft.com/en-us/library/cc178976.aspx gives good guidelines to start with web deployment.

Limitations

·         The method needs to work online when creating new documents. If you want typing documents in a train or in an airport, think about making an offline replica of a web application with templates, or saving templates on your PC.

·         To deploy the templates, you have to prepare XML files, preview and thumbnail images. If the preparation of XML files can be scripted, images have to be done manually.

Issues and work around

Deployment templates on SharePoint - authentication issue

If you used a template saved on a SharePoint site to create a document, you or other users can be prompted to log in to the SharePoint site when opening the document. It happens even if anonymous access is enabled on the template site. If the login is ignored, the document still opens. This happens because of a known authentication issue between SharePoint and Office:

http://social.technet.microsoft.com/forums/en-US/sharepointadmin/thread/7c69af51-d1b1-4642-b5fc-548663dd4564/

http://webborg.blogspot.com/2007/12/how-to-open-office-document-in-document.html

After all fiddling on access settings, the conclusion was: don’t deploy Office templates on a SharePoint site.

An easy work around may be just publishing the document in PDF format.

International

LCID in folder names

Pay attention that the examples in http://technet.microsoft.com/en-us/library/cc178976.aspx have 1033, the ID of the US English language locale. If the language of Microsoft Office user interface is different from English, the templates will not be shown. The XML files have to be b adapted. If users in your organization have different locales, you have to prepare variations of XML files per language. If the user interface of Microsoft Office on a PC has been changed, the templates have to be reinstalled.

Non-Latin characters

If your language is using other characters than 26 “standard” Latin letters, you have to encode the characters in XML files explicitly. In particular, it is required for Latin characters with diacritics (accents, umlauts, etc.) See an example:

<o:featuredtemplate title="PV r&#233;union" source="http://templateprovider.client.com/templates/ PV%20reunion%20FR.dotx">

Here the (ANSI) code &#233; represents the Latin letter with accent é.

The provider names in the registry also have to convert such characters. For example, to get é, you have to use the character with ANSI code 130 (shown as comma in text files):

HKCU\Software\Microsoft\Office\12.0\Common\Spotlight\Providers\Comit‚ for Comité

Sorting issue – numbers sorted as texts

Normally the template thumbnails are shown in the same order as they are listed in the XML file. But if a template group contains more than nine templates, their order in UI is different. It happens because templates get ordinal numbers used in registry keys and folder names. And both these values are sorted as texts, so that 10 and 19 come before 2. If you want to show thumbnails in proper order, make a formula which sorts the original XML entries in the way which is turned correctly when sorted as a text.

Delays

When the templates are just installed on a PC, the groups are shown in the New Document dialog box, but template thumbnails are not. Go out and go in, then you get the templates.

Different versions of Windows

Office 2007 works in Windows XP or later. But the structure of the registry and the folders is different in Windows 7, Vista and XP. So the scripts used to install or to uninstall the templates will also be different.

Bulk processing

Our client is using about 200 different Office templates varied by document type, language, institute, and availability of mail merge. Their client PC’s have to be maintained consistently.

The needed XML files can be created either by software utilities or by Excel spreadsheets with formulas based on lists of templates.

The installation of the templates is done by a batch file which uses commands of getting, creating and setting registry keys. The script can identify the Windows version and the language locale of Microsoft Office user interface, and adapt the installation accordingly:

rem works for both Vista and XP

reg query "HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Common\LanguageResources" /v UILanguage >c:\temp\uilang.txt

rem check Dutch

find "413" c:\temp\uilang.txt

if %errorlevel% equ 0 goto setlang1043

rem check French

find "40C" c:\temp\uilang.txt

if %errorlevel% equ 0 goto setlang1036

rem check German

find "407" c:\temp\uilang.txt

if %errorlevel% equ 0 goto setlang1031

del c:\temp\uilang.txt /f /q

This script creates one group of Word templates entitled “Comité”:

:regkey

:source

:langid

set regkey=HKCU\Software\Microsoft\Office\12.0\Common\Spotlight

set source=http://templateprovider.client.com

:setlang1036

set langid=_fr

reg add %regkey%\Providers /f

reg add "%regkey%\Providers\Comit‚" /f

reg add "%regkey%\Providers\Comit‚" /v ServiceURL /d "%source%/xml/comite_wd%langid%.xml" /f

reg add "%regkey%\Providers\Comit‚" /v Application /d "WD" /f

A good guide about managing registry keys in command prompt can be found here:

http://www.chaminade.org/MIS/Articles/RegistryEdit.htm

The batch file itself can be created by a script.

Don’t forget about keeping systems clean. Together with the installation batch file, foresee another one to uninstall the templates. Put the code to clean up the registry and the Office folders for any template which was ever used in the organization. Remember that the system creates several registry keys and folders in user profile for each template, and all of them have to be deleted when uninstalling the template. If it is not done, the obsolete template versions or group titles may stay in cache and pop up when the user tries to open the latest version.

Here is a sample script of clean uninstall of one group of templates in Vista:

:regkey

:locfiles

:spotlight

:cookies

set regkey=HKCU\Software\Microsoft\Office\12.0\Common\Spotlight

set locfiles=http://templateprovider.client.com/

set spotlight="C:\Users\%username%\AppData\Local\Microsoft\Office\Spotlight\Office 12"

set cookies="C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Cookies"

rem Deletion of Providers registry keys per organisation/Office application

reg delete "%regkey%\Providers\Client docx" /f

reg delete "%regkey%\Content\Client docx" /f

rem Cleaning cookies

del %cookies%"\*client*.txt"

rem Cleaning cache

rd %spotlight%"\Client docx" /s /q

and in XP:

:regkey

:locfiles

:spotlight

:cookies

set regkey=HKCU\Software\Microsoft\Office\12.0\Common\Spotlight

set locfiles=http://templateprovider.client.com/

set spotlight="C:\Documents and Settings\%username%\Local Settings\Application Data\Microsoft\Office\Spotlight\Office 12"

set cookies="C:\Documents and Settings\%username%\Cookies"

rem Deletion of Providers registry keys per organisation/Office application

reg delete "%regkey%\Providers\Client docx" /f

reg delete "%regkey%\Content\Client docx" /f

rem Cleaning cookies

del %cookies%"\*client*.txt"

rem Cleaning cache

rd %spotlight%"\Client docx" /s /q

The batch files prepared for Vista run perfectly in Windows 7 when started from file system. You can easily start the batch files from web locations (e.g. SharePoint site) in Vista and XP, but in Windows 7 they will not work: the access will be denied. The bacth files have to be copied to file system and started from there.

Posted by Viktor Bardadym | Leave your feedback

Mar
08

Unexpected conversion of links in SharePoint 2007 rich text content

Imagine the following scenario. You are typing some rich text entry on your SharePoint intranet with the internal URL http://intranet/. It might be a blog post, a discussion board, or just a content editor web part. You insert a link to other intranet site, like http://intranet.client.com. When you test the link, it looks like you want, but it works as just http://intranet/.

image image

If the site has alternate access mapping (AAM) with several web applications (for example, with different authentication), and default or intranet AAM has such short form (in the following example it’s http://portal/), all instances of the website convert the link this way:

image

(normally it ends with 404 error)

So SharePoint converts internal links to relative and overrules the conversion for such external links. The links which have the same beginning as default or intranet site URL are converted to relative ones, and then they are interpreted as being located on the default URL:

 

image

 image

How does SharePoint do the translation? Possible scenarios:
a) In real time every time the page is loaded. This means that in the database, the absolute link is still there.
b) in the background process (database) (not very probable).
c) When the user saves the content.

Shortly after saving, on the back end (in the content database, table AllUserData, field ntext2) the links are already relative:

<div class=ExternalClass97C68512A4184122B15D3302EC759305>
<div><a href="http://portal.client.org">http://portal.client.org</a></div>
<div><a href="/">http://intranet.client.com</a> </div></div>

What happens when you add additional alternative access mappings AFTER you already entered content? The relative URL’s are no more updated, they stay as they were with an old AAM.

So this conversion takes place when the user saves the content (scenario c).

Cheating like trying to put a slash next to short URL in AAM doesn’t work, the extra slash is cleaned on saving.

This behavior was noticed a long time ago and not fixed by now in SP 2007:

http://www.eggheadcafe.com/software/aspnet/30556472/directrelative-links-in.aspx

http://www.toddklindt.com/blog/Lists/Posts/Post.aspx?ID=57

http://blog.mastykarz.nl/inconvenient-content-editor-web-part/

Luckily in SharePoint 2010 this bug is fixed.

Posted by Viktor Bardadym | Leave your feedback

Nov
03

ASP.Net Exception Reporter

Orbit One has developed a unique solution that allows you to track and analyse “unhandled exceptions” in the code of web applications. “Unhandled exceptions” are problems that are not supposed to happen.
No system is perfect and environmental changes as well as different types of clients devices (browsers) can result in small issues.
You can make a friendly error page that explains the user an issue has happened, and invite him to try his action again.
If the problem remains, the user can click on a link and send an email to your support.
This email contains the unique reference number of the issue.
Your development team can monitor and fix the issues as soon as possible.
All issues are centralized in a database, allowing your team to quickly find detailed information about the problem.
This unique solution allows you to be efficient and provide high quality web applications.


elmahws1.png

You can find more information, the code, documentation and ready to use installers on Codeplex.

Posted by Wim De Coninck | Leave your feedback

Oct
06

Minimum Dynamics CRM Permissions

When configuring security roles in Dynamics CRM, a system administrator is situated between Scylla, allowing users things they shouldn’t do, (and, believe me, the users will do it very soon once permitted) and Charybdis, blocking users’ work. And K.I.S.S. advices, like “leave only read permissions just to the entities we use”, or “use only out-of-the-box CRM permissions, or their copies with minimal changes“ may lead the user to one of these beasts.

To perform an action within CRM, the user may need various permissions that don’t necessarily link link with each other, and which are located far away from each other in the user interface Security Roles.
To choose the right permissions you need an understanding of processes within Dynamics CRM.
This post lists the minimal permissions for several important functionalities of Microsoft Dynamics CRM and explains the backgrounds of them.
In general it is advised to test each new security role with an “alter ego” user having this role.

First login


- Business Management – User Settings – Write – User
First login 
Even if you create a 100% read-only user, let him write his user settings. If a user doesn’t have this permission, on the first login he gets an “Insufficient Permissions” error, because CRM cannot set & save his default entity in UI.
If you still have a good reason for blocking users to save their settings (via Tools - Options), you can block this permission. But then you have to follow these steps for every new user:
- assign System Administrator security role to the new user;
- log in as the new user;
- in Tools – Options slect the default enityt for the user(e.g. Accounts) and save user settings;
- log off;
- remove System Administrator security role and assign the actual security roleto the user.
Set default entity
 

Create an Activity


Looks simple: Core Records – Activities – Create – User. After it, the user can create an activity. But when saving, the user gets an error message ”The logged-on user does not have the appropriate security permissions…”. First of all, activities require Append To rights (don’t ask me why). Good enough for tasks.
Letters, faxes, phone calls and e-mails always have another party: a lead, a contact, a user (to send correspondence to your colleagues), and possibly an account. They have to be appended to other entities, so they need Append rights. And recipients’ entities need Append To.
It goes well with all types of activities except appointments. On saving an appointment, the user gets the same error message, followed by “General Failure in Scheduling Engine”. The first error happens because other users will not see the appointment if it is not shared. The second means that all appointments in the CRM have to be checked with the service calendar for availability, even if users don’t use the service calendar directly.
Add Core Records – Activity - Share (at least for business unit, not just for user) and Service management – Search Availability permissions  and get it working: 
Create an activity
Create an activity
Create an activity

Track an Activity in CRM


Was the above adventure enough to track Outlook entities in CRM? Oops, we get ”The logged-on user does not have the appropriate security permissions…” again. Business Management – Sync to Outlook? Right, but not sufficient. You also need Write access to activities.
Track an activity in CRM
Some sources (e.g.
http://social.microsoft.com/Forums/en-US/crmdeployment/thread/3451e18a-4afd-4436-b0b9-8ebd94156f67) refer to the necessity of read access to all of these records: account, contact, lead, user, and queue. The test shows that some of these entities, like account and queue, may be blocked, and the user still can track the activity (possibly changed by a rollup). The entities you select for Read & Append To access will be available in user’s Set Regarding dialog.

Send Mail Merge Letters


The obvious selections are:
- Business management – Mail Merge (from Outlook) and/or Web Mail Merge (from web interface);
- Core Records – Mail Merge Template – Read;
- Core Records – [used recipient entities, e.g. Lead, Account, Contact] – Read;
Send mail merge letters
Then users have to select the recipients in one of the ways:
- Advanced Find: Core Records – Saved View – Read – User, or
- Marketing List: Marketing  – Marketing List – Create – User, or – Read – Business Unit, or
- Quick Campaign: Marketing  – Create Quick Campaign.
They still don’t get Word icon on your workspace? Ah, like monsieur Jourdain didn’t realize that his speech was  prose, we don’t realize that mail merge is an activity. Moreover an activity has to be appended to the entities to which we send the letters. So we have to add the following permissions:
- Core Records – [used recipient entities] – Append To;
- Core Records – Activity – Create, Read, Append – User.
Send mail merge letters

Create Queck Campaign


As well as Mail Merge, Quick Campaign requires permissions to create, write and append activities. Otherwise the Quick Campaign wizard starts looping.

Create Reports with Report Wizard


When a user with custom security role tries to create a new report, he gets Insufficient Permissions error. The security role has all permissions regarding reports, but Report Wizard still doesn’t start. It happens in Microsoft Dynamics CRM 4.0 environments which have been migrated from 3.0.
Create reports with Report Wizard
The problem is that the new security role is missing some permission(s) and the same time the user interface is missing a control to change them. You can create a copy of System Administrator role and make the needed security role by removal of redundant permissions. (luckily “all to nothing” change takes just one click) This witching works like a charm.
There may be other permission issues solved the same way. (I saw a reference but can’t find it anymore)

Conclusion: by preference use (copies of) standard CRM security roles rathen than creating security roles from scratch.
Another advice you can find in literature and on the internet is not to change any predefined roles in the CRM.
Source:
http://www.techtalkz.com/microsoft-dynamics-crm/494850-insufficient-permission-report-wizard-crm4-0-a.html
 

Use Custom Entities


If a new custom entity is created, by default only the system administrator gets access to it. Other users will not see the entity. Even worse, they will not see any related values, lookup fileds in other entities,which use the custom entity. So whenever you create a new custom entity, give permissions to this entity for all security roles which are expected to use it, or any entities related with it. Configure the permissions on Custom Entities tab.

Use custom entities



Run Automatic Workflows


An action taken by the user may start a workflow which will create or update other records. For example, creating an opportunity may start a workflow which creates a follow-up task. Whenever you set up such a workflow, control that the user who may perform the original action cal also run workflows and take actions upon entities affected by the workflow.

Deletion of Records – The Rule and The Exceptions


The last but not the least, and it’s different. You can do anything but lay off of deleting blue suede CRM records.
Block deletion of records for all security roles except for System Administrator. By deleting records users will not only produce orphan records of other types. If a deleted record (like account) has parental relationship with other records, they all will be deleted.
Advise users to deactivate records, or to close activity records instead. One of many advantages is that you get “undo”. You can reactivate lead / customer records. In principle you can reactivate other types as well, but that’s another story.
The action to deactivate records has several reincarnations:
- Cancel (orders, invoices, cases and campaigns);
- Close (activities, opportunities and quotes);
- Convert (leads);
- Unpublish (workflows, duplicate detection rules and knowledge base articles).
And there are still quite some entities which cannot be deactivated:
- E-mails (it’s completed only when it’s sent. To delete an unsent draft, you have to enable deletion for all types of activities);
- Customer Relationships;
- Saved Views (Advanced Find);
- System jobs, like import, duplicate detection,…
- Reports (only revert to personal);
- Competitors;
- Products;
- Sales Literature;
- Quick Campaigns;
- Contracts;
- Announcements;
- Security Roles;
- Teams (neither deleted);
- Facilities/Equipment;
- Subjects.
As exception, deletion of some of them may be permitted for few power users. 
Deletion of records

Still don’t know what to do?


If this post does not cover your situation, or the advises don’t help, go for an advanced action.
- Enable  tracing:
http://support.microsoft.com/kb/907490
- Reproduce the error.
- In trace log search by error code and find the permission GUID:
Error: Server was unable to process request.
Error Number:
0x80040220
Error Message: SecLib::CrmCheckPrivilege failed. Returned hr = -2147220960 on UserId: e65023ae-54d1-da11-8e39-00145e3d5192 and PrivilegeId: a8ecac53-09e8-4a13-b598-8d8c87bc3d33
- Identify the missing permissions by querying the permission GUID in the CRM database, as advised by Microsoft: http://support.microsoft.com/kb/953962.
select Name,  * from PrivilegeBase where PrivilegeId = 'a8ecac53-09e8-4a13-b598-8d8c87bc3d33'
Posted by Viktor Bardadym | 1 Comment

Oct
03

Discover HD videoconferencing

Orbit One provides videoconferencing solutions based on LifeSize equipment.
In this PowerPoint presentation we share our tips and guidelines.

image

  • Why videoconferencing
  • Types of videoconferencing
  • LifeSize 200 series models
  • Multiple monitors
  • Technical guidelines
  • Meeting Room adjustments
  • Additional equipment

http://www.slideshare.net/orbitone/high-definition-videoconferencing

Posted by Olivier Mangelschots | Leave your feedback

Oct
03

SlideShare

Find our PowerPoint presentations on http://www.slideshare.net/orbitone

  • NUnit vs MSTest
  • Continuous Integration
  • Interacting with the Exchange Web Services
  • ReportViewer Web Server Control
  • Introduction to Code Reviews
  • Office Communication Server Integration
  • Introduction and tips about Microsoft Dynamics CRM
  • Nintex - SharePoint Workflow

More to come!

Posted by Olivier Mangelschots | Leave your feedback

Sep
28

CRM Migration - Migrant’s Notes

When your customer decides that his legacy CRM system is junk, and he has to move all business data to Microsoft Dynamics CRM with your help, he doesn’t expect “junk in - junk out” effect.

What are the critical success factors and the things which need special control during migration of business data to Dynamics CRM? See further – most of them are simple but often overlooked. And missing it may lead to stopping the migration, taking “ad hack” solutions, and making the migrated data even more junk than the original ones.

Good detailed plan

As for any activity with many details and dependencies, make detailed checklist of actions to perform and things to control on preprocessing, migration and postprocessing. Use top-to-bottom approach to plan actions: start with the most general and then bring more details to each level. Identify dependencies and put the actions in correct order.

Preparation on staging environment

Use staging Dynamics CRM environment to prepare the migration. When you (and your customer) are sure that all data are correctly migrated to the staging environment, do the migration to live. Backup & restore of the CRM organization database is not always an option: the restored CRM environment may not start at all. Backup & restore is not applicable at all if staging and live environments (and consequently Active Directory user accounts) are located in different domains.  

Keep the customizations of your staging environment identical to live as much as possible. Do not make parallel customizations in live and staging UI, even if they look identical. After such changes, further export and import of customizations between live and staging may become impossible.

No orphan records

In legacy CRM applications, records may have blank or invalid ID’s of related records. This can crash the software you use (for example, upgrade of ACT! database from an older format before migrating to MS CRM).

If possible, identify and fix or delete orphan records at early stage. In old ACT! and GoldMine databases you can do it on back end in dBase files.

Permissions

Migration tools and SDK’s may require that all users, active and historical, have permissions to create, append, append to, share,… If so, before the migration create all active and historical users in Active Directory and CRM and assign System Administrator role to them. After the migration secure CRM by removal of System Administrator role. Then you can assign all records owned by historical users to  actual  users, and only then disable historical user accounts.

Control size of fields

Control that all field values fit into size limits of CRM fields. Update size limits in CRM if needed. But keep in mind that updating sizes of standard fields (like address1_line1) may not solve the problem. Instead of size limit error, the import job can produce an unspecified server error.

Long values particularly happen in address fields. Consider splitting the address over several fields (address1_name, address1_line1, address1_line2 and address1_line3,…).

If you use standard CRM import, you can still save the refused records “on the fly”, split the long values, and repeat the import for refused records. 

Handling import errors

No special characters in field values

(like line end characters with ASCII codes 10 and 13)

Get rid of them before the import. Otherwise, sooner or later, they will make trouble. For example, if the data are imported from CSV files via standard CRM import, line breaks can break a record line into several, even if text qualifiers are used.

Notepad++ is a good tool to identify them in text files (e. g. CSV).

Control business required values

Control that all business required fields are 100% populated.

Control unexpected intelligence of your tools

If you export data from Excel , or use Excel to process the data, don’t be surprised with telephone numbers like 8.61E+12 or -166.0405405, while the original numbers are 8612345678910 and +32-9/222-99-99. The first one is a rounded “approximate” phone number in scientific format (8.61 x 1012), and the second is a “calculated” phone number (have you ever dialed an approximate negative fractional phone?). Excel doesn’t have cell format for telephone numbers and treats such input as a big numeral in the first case, or as a valid formula in the second case.

Solution: convert such values to text by Excel function TEXT.

Person’s names

Some systems don’t explicitly split contacts’ given names and family names. Foresee the rules which defines given names and family names in Dynamics CRM as adequate as possible.

Take into account that:

  • both given names and family names may be multiple; (e. g. Juan Luis Gonzalez Fernandez)
  • family names may have prepositions, sometimes multiple (e. g. Van Den Bogerd or de la Croix), which have to stay with the names;
  • names may be accompanied by salutations, titles, military ranks  in various languages, sometimes multiple, (e. g. Prof. Dr. Ing. Von Hochenbalken) which have to be separated and saved to a different field;
  • delimiting of the above parts may be inconsistent (space, dot with space, just dot);
  • even if you would have a comprehensive dictionary of given names, in some cultures it’s different to distinct family names from given names; (for example Roger Vincent, Laurence Olivier, Marcu Matei)
  • the field lastname always has to get a non-empty value, since it is business required.

A possible action plan is:

  • prepare the dictionary of “normalized” prepositions and the dictionary of “normalized” titles.
  • prepare the script with the functions which identify and split the full name to its parts based on the most typical name format (e. g. [Titles ]Firstname Lastname). This is possible even in Excel with usage of VBA.

Correctly treat  “All in one” legacy contact records

Many popular contact management applications (Microsoft Outlook among them) use single record for account and contact. Other systems (like ACT! by Sage) allow limited number of multiple contact persons in one database record. The data model of Dynamics CRM is different, it uses single record per account and single record per contact. If you migrate the data from such sources to the CRM, you have to split it to two Dynamics CRM records and later to assign Parent Customer and Primary Contact relationships between them.

For the original records create unique ID’s and migrate these ID’s to both account and contact records. If the data come from multiple sources, indicate the data source in the ID. Upon importing  accounts and  contacts, match them using unique ID’s.

One account may have more than one contact. If you want to eliminate duplicate accounts, at the stage of preprocessing define primary records for obsolete accounts (if the data of accounts are identical, or you have no preferences for the primary account, you can do it automatically in Excel using formulas), and then map contacts to primary accounts. Such updates of CRM records and many other handy thongs may be done by the CRM Bulk Update and Export tool available on Codeplex.

Complete this mapping before the users start manual hunting for duplicates.

Find the best balance for duplicate detection and merge

The right moment to merge duplicates (preprocessing, migration, or postprocessing) depends on how clean the data are. The customer may have an idea that source A is cleaner than source B. If so, import source A first and non-duplicate data from source B next.

In principle, the source B can be imported first, followed by source A and update of the data with available values from the source A. Be careful with updates “per field” (like “take the value form better source if not blank, otherwise take the value from the worse source”). For example, a record from the worse source may have data in two address lines (address1_line1 and address1_line2), while the corresponding record form the better source has only address1_line1. As a result, this rule may give a mixture of lines taken from two different addresses.

If after all the customer realizes that he needs company name from one source, e-mail address from another, and VAT code from the third (like a young lady form a classical comedy who searched a groom with nose of Mr. A., ears of Mr. B, and incomes of Mr. C.). If so, either let the customer to clean the data before the migration, or migrate all data, double and triple, to the CRM. CRM allows you to identify duplicates and to merge two records into one with specific selection of sections, fields from each merged records, or selection of the whole record.

Merge Duplicates

Merge Duplicates

Out-of-the-box duplicate detection in CRM is more than basic, but you can enhance it by using calculated match names. Normalize account or contact names by:

  • converting them to lower case and trimming;
  • converting letters with diacritics to standard Latin letters (e.g. Maïté to maite);
  • removal of texts inside parentheses, like alternative spellings or comments;
  • removal of punctuation marks and special characters (at this stage better to replace punctuation marks with spaces, since they delimit single words);
  • removal of common abbreviations, like English Ltd, German GmbH, or French SPRL;
  • removal of spaces.

The order of the above actions is important.

This matching method was compared with six more sophisticated metrics used to find duplicates (Jaro-Winkler, Jaro, Levenstein, Monge-Elkan, Needleman-Wunch, Smith-Waterman-Gotoh) on the migrated business data. In 95% percent of cases it gave the same or better matches as any other method, and the results, even wrong, were much more obvious for the users. The failures of this method normally had words in different order, like “University of Antwerpen” vs. “Antwerpen University”.

A match name plugin used for duplicate detection can be found on Codeplex.

International challenges

Control that the data prepared to import comply with your language and regional settings:

  • date formats: dd-MM-yyyy vs. MM-dd-yyyy.

For specific types of values in activity records third party migration tools accept only dates in English (US) format. This can make problems if in client's system the regional settings of Windows or CRM are different. If it happens, change system and CRM data formats to English US, and convert all dates in input data to this format.

  • letters with diacritics and non-Latin letters.

Control how your migration tool treats these characters. If you use bulk update tools, verify that their input data have Unicode format.

  • use of languages and geographical names.

In principle each record has to be in the language you want to communicate to the customer. But this makes use names of multilingual countries (like Switzerland or Belgium) inconsistent. As a result, validation scripts for country specific formats (like ones for telephone numbers) become more difficult. Instead, you can normalize country names to standard English names. Keep in mind that even if you use ISO standard, it’s not always a perfect reference. Say, the name “Taiwan, Province of China” advised by ISO 3166-1 is an insult for Taiwanese people.

Dynamics CRM Import.

If speech synthesis is comparable with getting toothpaste out of a tube, speech recognition is like trying to get the toothpaste back in. (Dr. J. Holmes, expert in speech processing)

 

The same is absolutely valid for Dynamics CRM export  and import.

 

Nevertheless, out-of-the-box import can be used to upload contacts from Outlook contact lists exported to Excel. Users can import the data to the CRM by building a data map between the data table in CSV format and the CRM entity attributes, and then by running an import job. Of course, you have to control that

  • all records being imported have all business required values;
  • there are no duplicate records within the import list and between the import list and the CRM (active and inactive);
  • the CSV files have to be really COMMA-separated, since other characters (tab or semicolon) are not accepted in sample files used in manual mapping. 

 

And even after it the import will not help with lookup and picklist attributes, because the export has their values, while the import requires their ID's (GUID's for lookup values, and numeric ID's for picklist values).

 

There is still a way to import the entities with lookup and picklist attributes. (thanks to CRM guru Jim Steiger) Be careful when following it, since any deviation will stop the process.

 

Good log

If you run scripts which change users’ data (for example, normalizes telephone numbers), foresee that the script informs your customers about:

  • all changes done in the system (so that the customer can handle all information he may miss after the cleanup, like the six more phone numbers, or a comment in the same field)

o   what type of record

o   what record

o   old value

o   new value

  • all suspicious data in fields which are left unchanged,
  • all errors happened during processing, with specific error messages,
  • nothing else (like changing assignment of the old value back to the field).

Since log may get long, foresee easy conversion of the log to spreadsheet or database, which will help to filter by specific type of issue, group records by owner, etc.

Good luck!

Posted by Viktor Bardadym | Leave your feedback

Sep
25

Creating custom commands for the Composite Application library(Prism v2)

The Composite Application Library helps architects and developers create composite Windows Presentation Foundation (WPF) and Silverlight applications. Composite applications are composed of discrete, functionally complete, pieces that work together to create a single, integrated user interface. The Composite Application Library accelerates the development of composite applications using proven design patterns to help you build these types of applications.

Commands are a way to handle user interface (UI) actions. They are a loosely coupled way to bind the UI to the logic that performs the action.

When building composite applications, presentation design patterns such as Model-View-Presenter (MVP) and Model-View-Controller (MVC) are often used to separate the UI logic from the UI layout and presentation. When implementing these patterns with Windows Presentation Foundation (WPF), the presenter or controller handles commands but lives outside the logical tree. WPF-routed commands deliver command messages through UI elements in the tree, but the elements outside the tree will not receive these messages because they only propagate events up or down from the focused element or an explicitly stated target element. Additionally, the WPF-routed commands require a command handler in the code behind.

The Composite Application Library introduces two new commands that can be routed outside the boundaries of the logical tree and that do not require handling logic in the code behind. The commands are custom implementations of the ICommand interface defined by WPF, and they implement their own routing mechanism to get the command messages delivered to objects outside of the logical tree. The commands in the Composite Application Library include DelegateCommand and CompositeCommand.

The command support in WPF is at this moment rather limited. Very few of the default controls support binding to a command. One of the controls that has a Command dependency property is the Button.


If we want to execute some code on button press and we want to leverage the commanding support, we need a few things in the view model and in the XAML view:

1. a property for the command

public ICommand ClickCommand {get; set;} 

2. Initialization code for the command (eventually in the view model’s constructor)

public MyConstructor()
{
ClickCommand = new DelegateCommand<object>(OnClickCommand);
}

3. Command handler:

private void OnClickCommand(object argument)
{ /**/ }

4. and some XAML code in the view that guarantees the command will be executed on button click:

<Button Height="24" x:Name="MyButton"  
Command=”{Binding ClickCommand}”/>

This is straightforward if you are familiar with the M-V-VM pattern.

Let’s consider another scenario where we need to execute a command for the lost focus event of a TextBox. To be able to solve this in the same manner as above we would need to use the Command dependency property of the TextBox and bind a DelegateCommand to it.

Unfortunately, the TextBox does not accept commands by default for the lost focus event.

A solution to the problem is to use the attached properties feature of WPF.

The goal is to create an attached property for the TextBox. The attached property’s name will also be Command and the command bound to it will handle the PreviewLostKeyboardFocus event. After we have this, we will be able to write the following code in the XAML view:

<UserControl xmlns:Commands= "clr-namespace:{namespace containing the attached command class}">
<TextBox Commands:PreviewLostKeyboardFocus.Command="{Binding MyTextBoxPreviewLostKeyboardFocus}"/>
</UserControl>

The code in the view model is identical as for the Button scenario (but with suggestive variable and method names of course):

public ICommand LostFocusCommand {get; set;}
public MyConstructor()
{
ClickCommand = new DelegateCommand<object>(OnLostFocusCommand);
}
private void OnLostFocusCommand(object argument)
{ … }

Now let’s dive into the implementation of the attached CommandProperty.
public class PreviewLostKeyboardFocus
{
/*Dependency property for the Command attached property.
For the Command property to be bindable it has to be dependency property.*/
public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached(
"Command",
typeof (ICommand),
typeof (PreviewLostKeyboardFocus),
new PropertyMetadata(OnSetCommandCallback));

public static readonly DependencyProperty LostFocusCommandBehaviorProperty =
DependencyProperty.RegisterAttached("LostFocusCommandBehavior",
typeof (TextBoxLostFocusCommandBehavior),
typeof (PreviewLostKeyboardFocus),
null);

/*Acessor methods for the Command attached property*/
public static void SetCommand(TextBox textBox, ICommand command)
{
textBox.SetValue(CommandProperty, command);
}

public static ICommand GetCommand(TextBox textBox)
{
return textBox.GetValue(CommandProperty) as ICommand;
}

/*Callback executed when the Command property is databound*/
private static void OnSetCommandCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBox = d as TextBox;
if (textBox != null)
{
TextBoxLostFocusCommandBehavior behavior = GetOrCreateBehavior(textBox, e.NewValue as ICommand);
}
}

/*Creates the command behavior if it does not already exist*/
private static TextBoxLostFocusCommandBehavior GetOrCreateBehavior(TextBox textBox, ICommand command)
{
var behavior = textBox.GetValue(LostFocusCommandBehaviorProperty) as TextBoxLostFocusCommandBehavior;
if (behavior == null)
{
behavior = new TextBoxLostFocusCommandBehavior(textBox, command);
textBox.SetValue(LostFocusCommandBehaviorProperty, behavior);
}
return behavior;
}

#region Nested type: TextBoxLostFocusCommandBehavior

/*Wrapper for the PreviewLostKeyboardFocus event*/
public class TextBoxLostFocusCommandBehavior : CommandBehaviorBase<TextBox>
{
public TextBoxLostFocusCommandBehavior(TextBox textBox, ICommand command) : base(textBox)
{
Command = command;
textBox.PreviewLostKeyboardFocus += (sender, args) => Command.Execute(new PreviewLostKeyboardFocusCommandArgs
{
Sender = (TextBox) sender,
KeyboardFocusChangedEventArgs = args
});
}
}

#endregion
}

As it’s obvious from the event wrapper class, the event forwards the sender and the event arguments to the command. So the command’s handler has access to the same data as the event itself. the PreviewLostKeyboardFocusCommandArgs  class is a custom class used to transfer parameters:

public class PreviewLostKeyboardFocusCommandArgs
{
public TextBox Sender { get; set; }
public KeyboardFocusChangedEventArgs KeyboardFocusChangedEventArgs { get; set; }}

The PreviewLostKeyboardFocus class might seem quite verbose, but this is the standard WPF way of defining attached properties that can take part in the data binding binding process.

Most of the code is standard and can be extracted in a R# template. The template can be downloaded here.

That’s it!

With just a little coding effort we can have a clean view and be able to wrap WPF event in Commands and handle the view events in the view model or controller(depending of the design approach).

Posted by Voicu Matei | 2 Comments

Sep
21

Format and validate phonenumbers in Dynamics CRM 4.0 Plugin

When importing data in Dynamics CRM 4.0 there is no client side code triggered, so to make sure you get phonenumbers (or anything else for that matter) in a clean format, you might want to consider creating a plugin that runs server side and generates an import failure to let the customer know some data is not valid in his imports.

This way the user knows when something went wrong and the correct data will still be imported.

To make this plugin work there is the issue of the country prefixes and areacodes that exist. Therefore it is necessary to create two new entities: Country and AreaCode.

The Country entity needs to contains the telephone prefix of that country (eg: belgium = 32, Netherlands = 33 …)

The AreaCode is contains a link to the country entity and contains the phone areacode. (eg: 9 for Ghent, Belgium …)

Ones this data is in CRM we can use it in our plugin through the webservice.

In the end the phonenumbers will be formatted in an outlook compatible format.

eg: +32 (9) 265.74.20

When using the installer inside the project on CodePlex the plugin will be registered for the create and update messages for lead, account and contact.

 

You can find the plugin on CodePlex in our Dynamics CRM 4.0 Plugins project

Posted by Wim De Coninck | Leave your feedback

Sep
08

Improved Duplicate Detection in Dynamics CRM

Why do I need it?

We've noticed the CRM Duplicate detection doesn't allow for much creativity, you can only create Duplicate Detection Rules with the following condition:

  • full string match
  • begins with (number of characters)
  • ends with (number of characters)


The problem with this is that people or companies aren't always entered in the same format. For instance if you look at our company name we would create the account with the name "Orbit One". Other people might write "Orbit One BVBA" (the bvba part is a type of business entity)
There are some other examples that come to mind:
"Dell NV" vs "Dell"
"HP Belgium" vs "HP"
"Gaëtan" vs "Gaetan"
"François" vs "Francois"
These exceptions will never be caught by the default CRM Duplicate detection.

How can I fix this?

We added the following attributes and filled the with data:

  • on account => new_matchname (contains the accounts name)
  • on contact => new_matchname (contains the contacts first + lastname)
  • on lead => new_matchcontact (contains the leads first+ lastname)
  • on lead => new_matchcompany (contains the lead company name)

The fields are filled with a normalized name. The process is:

  • to lower case and trim.
  • replace special characters (except parenthesis, a-z, 0-9, special characters like éèàç ..., and spaces) with empty string.
  • remove everything between the parentheses eg: "HP (was Compaq)" becomes "HP"
  • remove suffixes and prefixes that are type of business entity
  • remove all spaces
  • replace special characters (eg: é > e, à => a, ç => c, ñ => n, ...)

Next there need to be some new duplicate detection rules.

  • full string match on new_matchname for contact
  • full string match on new_matchname for account
  • full string match on new_matchcontact for lead (add companyname if needed in your specific cases)

The current implemented type of business entity which will be stripped are:

  • nv
  • sa
  • vzw
  • bvba
  • cvba
  • sarl
  • sprl
  • scrl
  • nvsa
  • bv
  • llc
  • gmbh
  • ltd
  • ag
  • kt
  • og
  • vof
  • cvoa
  • commva
  • commv
  • ebvba
  • ez
  • belgium

Duplicate Detection Jobs

In CRM you can add duplicate detection jobs by going to Settings > Data Management > Duplicate detection jobs

image

Create a new Duplicate detection job for for instance accounts. Make sure you filter on only active records. When you merge a duplicate record the record that isn’t the master record will be placed on inactive. So if you forget this filter you’ll keep getting the same duplicates ;-)

Once the job ran, you can see the duplicates entries.

image

What we think is another major pain in the a$$ is that you can only merge 2 records at a time. So not really in bulk… Maybe we will come up with a solution for this later :-)

 

You can find the Matchname plugin on CodePlex. There is an installer include so that you don’t need to worry about the plugin registration, creating the steps, …. More on this on CodePlex.

Posted by Wim De Coninck | Leave your feedback

 Next >>
Contact us - Raas Van Gaverestraat 83, 9000 Gent, Belgium - Tel. +32 (9) 330.15.00 - Privacy Statement - Sitemap - Sign In Developed with Microsoft Office SharePoint Server 2007