How-to series: Generate auto-numbers on custom entities (part 1)

Ok, in this series, I will try to explain how to generate auto-numbers on custom entities based on the user’s preferences (length of the auto-number, prefix, suffix, increment value, etc.)

This kind of customization is based on the plug-in created and sold by CRM Innovation.

I am not trying to copy their work, and therefore my plug-in is not as complete as theirs. Meaning…. if you want more complete functionalities, don’t ask me but BUY their plug-in!

The approach I will be using is very simple:

  1. Use an organization-owned entity for the users to configure the auto-numbering features
  2. Use a plug-in to generate an auto-number based on the user’s preferences

NB: I am not saying this is the best approach to this kind of feature but it shows how to use various techniques (JavaScript, C#) to customize Microsoft CRM. In this first series, I will describe the first step and explain the JavaScript used behind the customization.

Let’s get to work!

Create the organization-owned “Auto Number” entity

  1. Go to “Settings / Customizations” and create a new entity called ‘Auto Number’ (or whatever your language is, in French it would be ‘Numéro auto’)image
  2. Instead of using the default ‘Name’ field as-is, rename it to ‘Entity Name (schema)’ and change its schema name to ‘New_Entityname’; this field is going to store the selected entity schema name (physical name)image
  3. Click the “Save” button to generate the new custom entity
  4. Now we are going to create a couple of custom attributes that will be used to store various information:
    Name Used for Type Length
    Attribute Name Schema name of the attribute that will store the generated number varchar 100
    Attribute Display Display name of the attribute that will store the generated number varchar 100
    Entity Display Display name of the entity that will use the generated number varchar 100
    Entity Type Code The entity type code varchar 100
    Length The length of the generated number int  
    Increment The increment value for the generated number int  
    Prefix The prefix to use during the number generation (optional) varchar 100
    Suffix The suffix to use during the number generation (optional) varchar 100
    Example An example of generated number varchar 100
  5. When all the attributes have been created, this is the looks of the default form: image
  6. The purpose of this customization is to render the first two attributes (‘Entité’ [Entity] and ‘Attribut’ [Attribute]) as dynamic drop down lists: the first will allow the user to select the entity and the second will allow the user to select the attribute that will store the automatic identification numberimage
  7. The code that deals with the dynamic drop-down list comes from Thuta’s CRM blog and is available below with some explanations:
    crmForm.all.xrm_entitynamedisplay.ForceSubmit = true;
    crmForm.all.xrm_attributenamedisplay.ForceSubmit = true;
    crmForm.all.xrm_numberingexample.ForceSubmit = true;
    
    // Function that will load the attribute drop down list and store the entity's drop down list selected value
    entityOnChange = function () {
        crmForm.all.xrm_entityname.DataValue = document.getElementById('xrm_entitynamedisplay').options[document.getElementById('xrm_entitynamedisplay').selectedIndex].getAttribute('schemaName');
        crmForm.all.xrm_entitytypecode.DataValue = document.getElementById('xrm_entitynamedisplay').options[document.getElementById('xrm_entitynamedisplay').selectedIndex].getAttribute('entitytypeid');
    
        var schemaName = document.getElementById('xrm_entitynamedisplay').options[document.getElementById('xrm_entitynamedisplay').selectedIndex].getAttribute('schemaName');
        var request = "<?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>" +
                      "     <Execute xmlns="http://schemas.microsoft.com/crm/2007/WebServices">" +
                      "         <Request xsi:type='RetrieveEntityRequest'>" +
                      "             <MetadataId>00000000-0000-0000-0000-000000000000</MetadataId>" +
                      "             <EntityItems>IncludeAttributes</EntityItems>" +
                      "             <LogicalName>" + schemaName + "</LogicalName>" +
                      "             <RetrieveAsIfPublished>true</RetrieveAsIfPublished>" +
                      "         </Request>" +
                      "     </Execute>" +
                      " </soap:Body>" +
                      "</soap:Envelope>";
    
        var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
        xmlHttpRequest.Open("POST", "/mscrmservices/2007/MetadataService.asmx", false);
        xmlHttpRequest.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Execute");
        xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xmlHttpRequest.setRequestHeader("Content-Length", request.length);
        xmlHttpRequest.send(request);
    
        var result = xmlHttpRequest.responseXML;
        var schemaNames = result.selectNodes("//EntityMetadata/Attributes/Attribute");
    
        ConvertAttributeToPicklist('xrm_attributenamedisplay', schemaNames);
    }
    // Function that will store the attribute's drop down list selected value
    attribOnChange = function () {
        crmForm.all.xrm_attributename.DataValue = document.getElementById('xrm_attributenamedisplay').options[document.getElementById('xrm_attributenamedisplay').selectedIndex].getAttribute('schemaName');
    }
    // Function that converts the entity textbox to a drop down list
    function ConvertEntityToPicklist(fieldName, dataItems) {
        var defaultValue = crmForm.all[fieldName].DataValue;
        var table = crmForm.all[fieldName + "_d"];
        var select = "<select req='0' id='" + fieldName + "' name='" + fieldName + "' defaultSelected='' class='ms-crm-SelectBox' tabindex='1170' onchange='javascript:entityOnChange();'>";
        var defaultValueFound = false;
    
        for (var i = 0; i < dataItems.length; i++) {
            if (dataItems[i].selectSingleNode('IsCustomizable').text == "true") {
                select += "<option value='" + dataItems[i].selectSingleNode('LogicalName').text + "' ";
                select += "entitytypeid='" + dataItems[i].selectSingleNode('ObjectTypeCode').text + "' ";
                select += "schemaName='" + dataItems[i].selectSingleNode('LogicalName').text + "'";
    
                if (dataItems[i].selectSingleNode('LogicalName').text == defaultValue) {
                    select += " SELECTED";
                    defaultValueFound = true;
                }
    
                select += ">" + dataItems[i].selectSingleNode('DisplayName/LocLabels/LocLabel/Label').text + "</option>";
            }
        }
    
        if ((defaultValue != null) && (defaultValue.length > 0) && !defaultValueFound)
            select += "<option value='" + defaultValue + "' SELECTED>" + defaultValue + "</option>";
    
        select += "</select>";
        table.innerHTML = select;
    
        entityOnChange();
    }
    // Function that converts the attribute textbox to a drop down list
    function ConvertAttributeToPicklist(fieldName, dataItems) {
        var defaultValue = crmForm.ObjectId != null ? crmForm.all[fieldName].DataValue : null;
        var table = crmForm.all[fieldName + "_d"];
        var select = "<select req='0' id='" + fieldName + "' name='" + fieldName + "' defaultSelected='' class='ms-crm-SelectBox' tabindex='1170' onchange='javascript:attribOnChange();'>";
        var defaultValueFound = false;
    
        for (var i = 0; i < dataItems.length; i++) {
            if (dataItems[i].selectSingleNode('DisplayName/LocLabels/LocLabel/Label') != null) {
                select += "<option value='" + dataItems[i].selectSingleNode('LogicalName').text + "' ";
                select += "schemaName='" + dataItems[i].selectSingleNode('LogicalName').text + "'";
    
                if (dataItems[i].selectSingleNode('LogicalName').text == defaultValue) {
                    select += " SELECTED";
                    defaultValueFound = true;
                }
    
                select += ">" + dataItems[i].selectSingleNode('DisplayName/LocLabels/LocLabel/Label').text + "</option>";
            }
        }
    
        if ((defaultValue != null) && (defaultValue.length > 0) && !defaultValueFound)
            select += "<option value='" + defaultValue + "' SELECTED>" + defaultValue + "</option>";
    
        select += "</select>";
        table.innerHTML = select;
    
        attribOnChange();
    }
    // Entity retrieval request: used to retrive the published entities
    var request = "<?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>" +
                  "    <Execute xmlns="http://schemas.microsoft.com/crm/2007/WebServices">" +
                  "      <Request xsi:type="RetrieveAllEntitiesRequest">" +
                  "        <RetrieveAsIfPublished>true</RetrieveAsIfPublished>" +
                  "        <MetadataItems>EntitiesOnly</MetadataItems>" +
                  "      </Request>" +
                  "    </Execute>" +
                  "  </soap:Body>" +
                  "</soap:Envelope>";
    
    var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
    xmlHttpRequest.Open("POST", "/mscrmservices/2007/MetadataService.asmx", false);
    xmlHttpRequest.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Execute");
    xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    xmlHttpRequest.setRequestHeader("Content-Length", request.length);
    xmlHttpRequest.send(request);
    
    var result = xmlHttpRequest.responseXML;
    var schemaNames = result.selectNodes("//CrmMetadata/CrmMetadata");
    
    ConvertEntityToPicklist('xrm_entitynamedisplay', schemaNames);
  8. The final result should look like this once a new record is created:image

This first post of the series is to lay the groundwork of the following posts, which will deal with creating a plugin to generate a random number based on the information stored in the autonumber record.

Feel free to contact me for any question…Wink

3 thoughts on “How-to series: Generate auto-numbers on custom entities (part 1)”

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>