Blog

Saving Generated Documents to SharePoint

– 7 Minutes

Microsoft recently added functionality for one-click document generation to Dynamics 365. Although this is great functionality, it is a bit limited with regard to where it can save the generated document. Out of the box, we can add the SetWordTemplate action to a workflow, but that generates the document and saves it as an attachment to an annotation. What if you want to save it in SharePoint? We can accomplish this with a custom plugin.

Although Microsoft has added them to the online documentation, there are some actions available for us to call.

Action Input Parameters Output Parameters
Name Type Name Type
ExportWordDocument EntityTypeCode Int32 WordFile Byte[]
SelectedRecords String
SelectedTemplate EntityReference
UploadDocument Content Byte[] *None*
OverwriteExisting Boolean
Entity Entity
ParentEntityReference EntityReference

First, let's create some extension methods that will help us call these undocumented commands to generate either a Word or an Excel document.

if (typeof BGuidinger == "undefined") {
    BGuidinger = { __namespace: true };
}
if (typeof BGuidinger.Samples == "undefined") {
    BGuidinger.Samples = { __namespace: true };
}

BGuidinger.Samples.Sdk = {
    ExportWordDocument: function (templateId, entityType, entityId) {
        this.EntityTypeCode = entityType;
        this.SelectedRecords = "[ '{" + entityId + "}' ]";
        this.SelectedTemplate = {
            entityType: "documenttemplate",
            id: templateId
        };

        this.getMetadata = function () {
            return {
                operationName: "ExportWordDocument",
                operationType: 0,
                parameterTypes: {
                    "EntityTypeCode": {
                        "typeName": "Edm.Int32",
                        "structuralProperty": 1
                    },
                    "SelectedRecords": {
                        "typeName": "Edm.String",
                        "structuralProperty": 1
                    },
                    "SelectedTemplate": {
                        "typeName": "mscrm.documenttemplate",
                        "structuralProperty": 5
                    }
                }
            };
        };
    },
    UploadDocument: function (entityType, entityId, filename, content) {
        this.Content = content;
        this.OverwriteExisting = true;
        this.Entity = {
            entityType: 'sharepointdocument',
            id: '00000000-0000-0000-0000-000000000000',
            title: filename
        };
        this.ParentEntityReference = {
            entityType: entityType,
            id: entityId
        };

        this.getMetadata = function () {
            return {
                operationName: "UploadDocument",
                operationType: 0,
                parameterTypes: {
                    "Content": {
                        "typeName": "Edm.String",
                        "structuralProperty": 1
                    },
                    "OverwriteExisting": {
                        "typeName": "Edm.Boolean",
                        "structuralProperty": 1
                    },
                    "Entity": {
                        "typeName": "mscrm.sharepointdocument",
                        "structuralProperty": 5
                    },
                    "ParentEntityReference": {
                        "typeName": "mscrm.crmbaseentity",
                        "structuralProperty": 5
                    }
                }
            };
        };
    }
};

What's awesome about the UploadDocument action is we don't have to include a dependency on the SharePoint SDK (and deal with ILMerge...).  This is the same action Dynamics 365 uses when you upload a document through the UI (check the network trace when you upload a document).

Comments

No comments.