Word document from code

Sometimes you may want to generate a Word document from code in D365FO, which gives you much more control over the result than if you simply printed a report to Word.

Here is a very brief example of how you can do it.

Start with creating an X++ project. Then add a C# class library to the same solution (I called it WordLib). Right-click the C# project, use Manage NuGet Packages… and install DocumentFormat.OpenXml package.

Then add the following class:

using System.IO;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
 
namespace WordLib
{
    public class WordDoc
    {
        public Stream Create()
        {
            MemoryStream ms = new MemoryStream();
 
            using (WordprocessingDocument wordDocument =
                WordprocessingDocument.Create(ms, WordprocessingDocumentType.Document, true))
            {
                MainDocumentPart mainPart = wordDocument.AddMainDocumentPart();
 
                string text = "Do androids dream of electric sheep?";
                Body body = new Body(new Paragraph(new Run(new Text(text))));
 
                mainPart.Document = new Document(body);
            }
 
            return ms;
        }
    }
}

This code will create a very simple Word document, containing only a single line of text, and returns it as a memory stream. You would likely need something more complicated, but that’s out of scope of this blog post. You can get more information from Open XML SDK documentation.

Build the C# class library and we’re done with it; now we need to call it from X++.

Go to the X++ project, right-click References, chose Add Reference… and add a project reference to the C# library.

Then add a runnable class with the following code, which merely calls the library and returns the stream as a file to user:

class WordDocGeneratorSample
{        
    public static void main(Args _args)
    {     
        using (System.IO.Stream wordStream = new WordLib.WordDoc().Create())
        {
            File::SendFileToUser(wordStream, 'file.docx');
        }
    }
}

Set the class as the startup object, run the project and your browser should offer you the Word document for download.

7 Comments

  1. Hi Martin.

    I only started with this about an hour ago.

    I followed the instructions religiously, but I get the following error when I click the Action Menu Item (it executes WordDocGeneratorSample) on the front end: “Could not load file or assembly DocumentFormat.OpenXML ….. or one of its dependencies”
    I am reading up on referencing C# code in general. I have one question that I do not find an answer for: Why is it specifically the VS Project that references the C# library? (All the stuff I’ve read just states, like you did, to add the library as a reference in the project.) It does not make sense to me. I mean the project is a VS concept, nothing to do with the implementation of my C# library?

    • You should have two projects in a single solution – an X++ project and a C# class library. You want your X++ project to reference the C# class library (to be able to use the C# class), therefore you’ll go to the X++ project, right-click References and choose Add Reference…. This will show a dialog where you can select references from several sources (base class library, files…) and the active tab should be Projects, where you should see the class library project. That’s the reference you want to add.

Leave a Reply to Martin Dráb Cancel reply

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