Thursday, October 27, 2016

View or Download All attachments for single record

In MS CRM you can attach different types of documents to notes. There are some file extensions of attachments are blocked by default by CRM, also you can add / remove file extensions from blocked list.
You will find blocked extensions for attachment in Settings à Administration à System Settings.

In MS CRM you can attach one attachment per note, and to view attachment you have to download it, then only you can able to view.
Also to view attachments for particular record, we need to open each note and download individual.

To view all attachments of single record in single page, I create one solution with HTML web resource, which will give option to view (extensions restricted) attachments or download attachment from single page.


To create this solution I used one HTML web resource.

Steps to create view Attachment Page.
 1.      To show button on records form
a.      Create one Ribbon button “View Attachment” using ribbon workbench.

b.      In Button command Add Action – JavaScript Command.
c.       In JavaScript command call function – OpenViewAttachment


d.     If want you can add Display Rules or Enable Rules, for when to show this button.
2.      JavaScript library - new_js/contactScript.js

contactScript =
{
    OpenViewAttachment: function () {
        // get current Record Id
        var recordId = Xrm.Page.data.entity.getId();
        var customParam = encodeURIComponent("recordId=" + recordId);
        //pass current record Id to Web resource, to retrieve all attachments from note.
        Xrm.Utility.openWebResource("new_HTML/AttachmentViewer.html", customParam);
    },
}

1.      HTML Web resource
a.      In HTML web resource add script reference for jquery_1.10.2.js, Jquery_ui_1.10.4.min.js and ClientGlobalContext.js.aspx
b.      In Web resource, calling two functions when document is ready
                                                              i.      getDataParam()
This function is used to get query string parameter (recordId) which we passed from OpenViewAttachment function, when opening HTML web resource.
                                                           ii.      GetCurrentRecordAttachments()
This function will retrieve all notes with attachment, and show list of notes & attachment.
Here is complete code of HTML web resource 


<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="../ClientGlobalContext.js.aspx" type="text/javascript"></script>
    <script src="../new_js/jquery_1.10.2.js" type="text/javascript"></script>
    <script src="../new_js/Jquery_ui_1.10.4.min.js" type="text/javascript"></script>
    <style>
        .fixed_headers {
            width: 100%;
            table-layout: fixed;
            /*border-collapse: collapse;*/
            border: thin solid #b3b3b3;
        }

            .fixed_headers th {
                text-decoration: underline;
            }

            .fixed_headers th,
            .fixed_headers td {
                padding: 5px;
                text-align: left;
            }

                .fixed_headers td:nth-child(1),
                .fixed_headers th:nth-child(1) {
                    min-width: 5%;
                }

                .fixed_headers td:nth-child(2),
                .fixed_headers th:nth-child(2) {
                    min-width: 25%;
                }

                .fixed_headers td:nth-child(3),
                .fixed_headers th:nth-child(3) {
                    width: 10%;
                }

                .fixed_headers td:nth-child(4),
                .fixed_headers th:nth-child(4) {
                    width: 10%;
                }

                .fixed_headers td:nth-child(5),
                .fixed_headers th:nth-child(5) {
                    width: 25%;
                }

                .fixed_headers td:nth-child(6),
                .fixed_headers th:nth-child(6) {
                    width: 25%;
                }

            .fixed_headers thead {
                background-color: #b3ccff;
                color: #fdfdfd;
            }

                .fixed_headers thead tr {
                    display: block;
                    position: relative;
                }

            .fixed_headers tbody {
                display: block;
                overflow: auto;
                width: 100%;
                height: 200px;
            }

                .fixed_headers tbody tr:nth-child(even) {
                    background-color: #cce5ff;
                }

        .old_ie_wrapper {
            height: 200px;
            width: 100%;
            overflow-x: hidden;
            overflow-y: auto;
        }

            .old_ie_wrapper tbody {
                height: auto;
            }
    </style>

    <script type="text/javascript">
        var recordId;
        $(document).ready(function () {
            getDataParam();
            GetCurrentRecordAttachments();
        });

        function getDataParam() {
            var vals = new Array();
            if (location.search != "") {
                vals = location.search.substr(1).split("&");
                for (var i in vals) {
                    vals[i] = vals[i].replace(/\+/g, " ").split("=");
                }
                //look for the parameter named 'data'
                var found = false;
                for (var i in vals) {
                    if (vals[i][0].toLowerCase() == "data") {
                        parseDataValue(vals[i][1]);
                        break;
                    }
                }
            }
            else {
                noParams();
            }
        }

  function noParams() {
            alert('No data parameter was passed to this page.');
        }
        function parseDataValue(datavalue) {
            if (datavalue != "") {
                var vals = new Array();
                vals = decodeURIComponent(datavalue).split("&");
                for (var i in vals) {
                    vals[i] = vals[i].replace(/\+/g, " ").split("=");
                    if (vals[i][0].toLowerCase() == "recordid") {
                        recordId = vals[i][1];
                        recordId = recordId.replace('{', '');
                        recordId = recordId.replace('}', '');
                        break;
                    }
                }
            }
        }
        function GetCurrentRecordAttachments() {
            var container = $('#my-container'),
                table = $('< table class="fixed_headers" >');
            var thead = $('< thead >');
            var theadTr = $('< tr >');

            theadTr.append('< th > Subject</ th >');
            theadTr.append('< th > File Name</ th >');
            theadTr.append('< th > File Type</ th >');
            theadTr.append('< th > View / Download< /th >');
            thead.append(theadTr);
            table.append(thead);

            var viewInBrowser = ["image/png", "text/plain", "application/pdf", "image/jpg", "image/bmp"];

            var req = new XMLHttpRequest();
            req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.0/annotations?$select=annotationid,documentbody,filename,mimetype,subject&$filter=_objectid_value eq " + recordId + " and  isdocument eq true", true);         
 req.setRequestHeader("OData-MaxVersion", "4.0");
            req.setRequestHeader("OData-Version", "4.0");
            req.setRequestHeader("Accept", "application/json");
            req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
            req.setRequestHeader("Prefer", "odata.include-annotations=\"OData.Community.Display.V1.FormattedValue\"");
            req.onreadystatechange = function () {
                if (this.readyState === 4) {
                    req.onreadystatechange = null;
                    if (this.status === 200) {
                        var results = JSON.parse(this.response);
                        for (var i = 0; i < results.value.length; i++) {
                            var annotationid = results.value[i]["annotationid"];
                            var documentbody = results.value[i]["documentbody"];
                            var filename = results.value[i]["filename"];
                            var mimetype = results.value[i]["mimetype"];
                            var subject = results.value[i]["subject"];


                            var tr = $('< tr >');
                            tr.append('< td >' + subject + '< /td >');
                            tr.append('< td >' + filename + '< /td >');
                            var url = "data:" + mimetype + ";base64," + documentbody;
                            var id = "h" + i;
                            tr.append('< td >' + mimetype + ' < input id="' + id + '" type="hidden" value="' + url + '" />   < /td >');

                            var Isview = false;
                            for (var j = 0; j < viewInBrowser.length; j++) {
                                if (viewInBrowser[j] == mimetype) {
                                    Isview = true;
                                    break;
                                }
                            }

                            if (Isview) {
                                var alink = "< a id ='" + id + "' href='#' onclick='showData(this);' > View </ a >";
                                tr.append('< td >' + alink + '</ td >');
                            }
                            else {
                                var alink = "< a id ='" + id + "' href='#' onclick='showData(this);'> Download </ a >";
                                tr.append('< td >' + alink + '</ td>');
                            }

                            table.append(tr);
                        }
                    }
                    else {
                        alert(this.statusText);
                    }
                }
            };
            container.append(table);
            req.send();
        }
        function showData(ctrl) {
            var id = ctrl.id;
            var url = $('#' + id).val();
            document.getElementById("itempreview").src = url;
        }
    </script>
</head>
<body>
    <div id="my-container">
    </div>
    <br />
    <span style="font-weight: 700"> View Attachment</span>
    <div>
         <br />
        <iframe id="itempreview" style="height: 600px; width: 800px"></iframe>
    </div>
</body>
</html>




With this HTML web resource, we can view attachments which are images, PDF or text, if attachments are word document, excel, PowerPoint etc., and then need to download.

Hope this will help.. 

Wednesday, October 26, 2016

Xrm.Utility functions : openQuickCreate


There is another good function in Xrm.Utility object : openQuickCreate. This function is only available for CRM 2015 (update 1) online or later versions.
Using this function we can open quick create form for entity even there is not any direct relationship.
e.g. if you have any custom entity, and this custom entity is not has any relationship with contact but for some reason when this custom entity form opens, you want to create contact / want to open contact quick create, you can use this Xrm.Utility function.
With openQuickCreate function, you can set default values on form by passing parameters and/or by using query string parameters and/or using attribute mapping defined in relationship.
Common syntax for openQuickCreate is

Xrm.Utility.openQuickCreate(entityLogicalName,createFromEntity,parameters).then(successCallback, errorCallback);

To open any entity quick create form only entityLogicalName is required, other parameters are optional.

When wants to open just quick create form without setting any default values, then we can use

Xrm.Utility.openQuickCreate( "contact",);

This will open quick create form for contact entity.

For all details about parameters, please check


The complete example of openQuickCreateForm is

carScript = {

    onLoadEvent:function()
    {       
        var thisEntityRecord = {
            entityType: "new_car",
            id: Xrm.Page.data.entity.getId(),
            name: Xrm.Page.getAttribute('new_name').getValue()
        };
        var parameters = {};
        parameters["new_manufactureaddress"] = Xrm.Page.getAttribute('new_manufactureaddress').getValue(); 
  
        Xrm.Utility.openQuickCreate("new_manufacture", thisEntityRecord, parameters).then(carScript.setManfactureLookup,carScript.errorfun);

    },
    setManfactureLookup:function(manfObj)
    {
        var lookup = new Array();
        lookup.push(manfObj.savedEntityReference);
        Xrm.Page.getAttribute('new_manufactureid').setValue(lookup);
    },
    errorfun:function(error)
    {
        Xrm.Utility.alertDialog(error);
    },
};

This function is called on form load; once form is loaded, quick create form for Manufacture (custom entity) will be displayed.  Once quick create record is saved, setManfactureLookup is called, which will set Manufacture lookup in car entity.
 When quick create record saved, you will get saved record entity reference object in SuccessCallbackfunction.

Note: There is a limit of 10 nested quick create forms in the web application. If this limit is exceeded this function will open the full entity form rather than quick create form.