web
You’re offline. This is a read only version of the page.
close
Skip to main content
Community site session details

Community site session details

Session Id :

Create Excel file using OpenXML in Dynamics 365 Plugin

Spring Wave 2016 Profile Picture Spring Wave 2016 325
Let’s suppose you have following scenario for creation of excel file in CRM plugin.

Use OpenXml to create Excel file based on data in Customer (i.e. Account) and attach this file in email and send email to all contacts related to customer.

Let’s say you want to create excel file like this on the fly based on data in customer entity or its related entities.

ExcelImage

Note: Click here to download complete code of plugin and JS file from GitHub.

Here are main steps we need to do to accomplish above scenario

  1. Create plugin which will create excel file, create an email with customer info, attach excel file in email and send it to all contacts of customer.
  2. Create action for Customer entity (which is actually Account entity. Its logical name is account).
  3. Register plugin on action which we created in step 2.
  4. Write JS code to call action in step 2 which will automatically call plugin of step 1.
  5. Call JS on form load on Customer (account) form to test this whole recipe.
  6. Create Email template which we will be using while creating email in plugin.
  7. Excel file creation code

Step 1- Create Plugin

Create a class library project in VS 2015, like this I done

ClassLibrary.png

Add reference of OpenXml like this

DLLs.png

Now use ILMerge to merge OpenXml DLL with plugin’s DLL when we will build the project. You can do this easily by including these two packages into your project:

  • ILMerge
  • MSBuild.ILMerge.Task

For further details how I have done see following screenshots which explains step by step way to do this.

Nuget1.png

Nuget2

Nuget3.png

Nuget4.png

Now install MSBuild.ILMerge.Task

Nuget5

Nuget6.png

Nuget7.png

Now simply build the project, the final DLL size should be little bigger as you can see below.

DLLs_2.png

Step 2- Create action

Create a new action by clicking new button

Step2_1.png

Step2_2.png

Final look of action should be like this

Step2_3.png

Note: You must activate action to see it later in plugin step in plugin registration tool. As you can see in “Step 3” below. As you will start typing name of action in Message box, it will show complete name in intellisence.

Step 3 – Register plugin on action

After registering plugin from plugin registration tool, add a new step like this

Step3.png

Step 4 – Call Action by JS

Call the created action by following JS code

function callSendExcelFileInEmailAction() {
    debugger;
    //Alert.showLoading();
    var entityId = Xrm.Page.data.entity.getId().replace(/\{|\}/gi, '');
    var entityName = 'account';
    var entityPluralName = 'accounts';
    var actionUniqueName = 'new_SendExcelFileInEmail';

    var inputParams = null;
    var result = callEntityAction(entityId, entityName, entityPluralName, actionUniqueName, inputParams);
    debugger;
    if (result.ResponseData != null && result.ResponseData != undefined) {
        var pluginTrace = result.ResponseData['PluginTrace'];
        var message = result.ResponseData['Message'];
        if (message == 'Success')
        {
            alert('Excel file created successfully and send to contacts in email.');
        }
        else {
            alert('There is something wrong with file creation or email sending.');
        }
    }
}

Step 5 – Call JS on Customer form

Let’s say we call it on OnLoad of form, simply register this on form like this

Step4

Step 6 – Create Email template

I have created following template which is used in plugin code to send email

Step6_1.png

You have to create an email template like this

Step6_2.png

Step 7 – Excel file creation code

I created a separate class named “CustomerExcel” to generate excel file. There is a method named “CreateExcelDoc” which is handling all this stuff.

Have a look at the code below

public byte[] CreateExcelDoc()
        {
            MemoryStream memoryStream = new MemoryStream();
            Trace.AppendLine("CE=>---2...Inside CreateExcelDoc()");
            //FileNameWithPath = @"C:\_Temp\UNI STYLE TAILORING BR_131596023494075050_Accounts.xlsx";
            using (SpreadsheetDocument document = SpreadsheetDocument.Create(memoryStream, SpreadsheetDocumentType.Workbook))
            {
                WorkbookPart workbookPart = document.AddWorkbookPart();
                workbookPart.Workbook = new Workbook();

                WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
                worksheetPart.Worksheet = new Worksheet();

                WorkbookStylesPart wbsp = workbookPart.AddNewPart<WorkbookStylesPart>();
                //// add styles to sheet                
                Stylesheet stylesheet1 = new Stylesheet() { MCAttributes = new MarkupCompatibilityAttributes() { Ignorable = "x14ac" } };
                wbsp.Stylesheet = stylesheet1;//CreateStylesheet();
                wbsp.Stylesheet.Save();

                Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets());
                Sheet sheet = new Sheet() { Id = workbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = "Accounts" };

                sheet.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
                sheet.AddNamespaceDeclaration("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
                //sheet.AddNamespaceDeclaration("x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");

                sheets.Append(sheet);

                workbookPart.Workbook.Save();

                SheetData sheetData = worksheetPart.Worksheet.AppendChild(new SheetData());

                Columns _cols = new Columns(); // Created to allow bespoke width columns
                CreateColumns(document, worksheetPart.Worksheet, _cols);
                AddHeader(worksheetPart.Worksheet, new List<string>() { CustomerObj.CompanyName, string.Empty, string.Empty, string.Empty });
                worksheetPart = MergeRowCells(worksheetPart);
                AddHeader(worksheetPart.Worksheet, new List<string>() { "Account Number", "Product Name", "Fax", "Main Phone" });

                // Inserting each employee
                UInt32 currentRowNumber = Convert.ToUInt32(sheetData.ChildElements.Count()) + 1;
                int accountNumber = 123456;
                int fax = 92321555;
                int phone = 92321666;

                for (int i = 0; i < 5; i++)
                {
                    //var localDate = DateTime.UtcNow.ToLocalTime();
                    //var localDateTime = DateTime.SpecifyKind(localDate, DateTimeKind.Unspecified);
                    //string fromDate = ConvertCrmDateToUserDate(localDateTime).ToString();
                    //string toDate = ConvertCrmDateToUserDate(localDateTime.AddDays(2)).ToString();

                    string productName = "Product "+ (i+1).ToString();
                    accountNumber++;
                    Row dataRow = CreateExcelRow(accountNumber.ToString(), productName, fax.ToString(), phone.ToString(), currentRowNumber, false);
                    sheetData.AppendChild(dataRow);
                    currentRowNumber++;
                }

                wbsp.Stylesheet = CreateStylesheet_New(); //CreateStylesheet();
                wbsp.Stylesheet.Save();

                int countRows = sheetData.Elements<Row>().Count();

                if (countRows >= 3)
                {
                    Row row_1 = sheetData.Elements<Row>().ElementAt<Row>(0);
                    int index0 = 0;
                    foreach (Cell c in row_1.Elements<Cell>())
                    {
                        c.StyleIndex = Convert.ToUInt32(index0);
                    }

                    Row row_2 = sheetData.Elements<Row>().ElementAt<Row>(1);
                    int index1 = 1;
                    foreach (Cell c in row_2.Elements<Cell>())
                    {
                        c.StyleIndex = Convert.ToUInt32(index1);
                    }

                    for (int i = 0; i < sheetData.Elements<Row>().Count(); i++)
                    {
                        Row dataRow = sheetData.Elements<Row>().ElementAt(i);
                        if (i > 1)
                        {
                            int index2 = 2;
                            foreach (Cell c in dataRow.Elements<Cell>())
                            {
                                c.StyleIndex = Convert.ToUInt32(index2);
                            }
                        }
                    }
                }

                worksheetPart.Worksheet.Save();
            }
            Trace.AppendLine("CE=>---3...Executed method CreateExcelDoc()");
            return memoryStream.ToArray();
        }
Important! I have created excel file in memory which is more efficient than creating file on disk. It is also useful when we are working in CRM online environment where disk location cannot be retrieved.

 


This was originally posted here.

Comments

*This post is locked for comments