Generating Word Documents in Windows Store Applications

Since Word introduced Office Open XML (docx) file format, it became much easier to programmatically generate documents from applications without requiring Word to be installed on the machine for Word Automation to work. Not only was the new format well documented and basically a zipped XML file, there's also Open XML SDK available for download making the file manipulation even easier.

Unfortunately the latter doesn't work with Windows Store applications. While you can install the corresponding NuGet package in a Windows Store project, the app won't build any more once you do it. The assembly is not compiled as a portable class library and also depends on WPF base library WindowsBase.dll for the packaging API. Unless you have the time and resources available to work with Word files at the bare XML level, the only alternative available for Windows Store apps at the moment seems to be DocIO from Syncfusion sold as a part of Essential Studio for WinRT.

That's the main reason why it was chosen for a project I am currently working on. I don't have any previous experience with other Syncfusion controls but I must say I was disappointed a bit by DocIO documentation. I couldn't find any complete reference for all the classes and many examples seem overly simplistic to be used in real world scenarios. Still, by reading through all of the available documentation it soon became evident that the library supports only a small subset of Word features.

The only way to actually generate the required documents is to prepare them as templates in advance and fill in the missing information programmatically. That's not too bad since it's the preferred way anyway unless you want to modify your code every time some detail in a document changes. Fortunately bookmarks are supported and can be used as anchor points for inserting content. Since this operation isn't documented very well either, I was forced to learn it by playing around with the API. The remainder of this post describes what I found out and should save you some time if you're taking on a similar task.

All document manipulation is performed in memory. Therefore the basic workflow is to load the template document from a file, modify it and save the resulting document to a new file:

WordDocument document;
using (var stream = await templateStorageFile.OpenStreamForReadAsync())
{
    document = new WordDocument(stream);
}

// modify the document here

await document.SaveAsync(outputStorageFile, FormatType.Docx);

The most common operation should be inserting some text at the bookmark location:

var bookmarksNavigator = new BookmarksNavigator(document);
bookmarksNavigator.MoveToBookmark(bookmarkName);
bookmarksNavigator.InsertText(text, true);

The best idea is to already use the right character format in the template document when defining the bookmark. Though if you really need to, you can still apply a custom character format to the inserted text:

var textRange = bookmarksNavigator.InsertText(text, true);
textRange.ApplyCharacterFormat(characterFormat);

Inserting images instead of text is also supported:

var bookmarksNavigator = new BookmarksNavigator(document);
bookmarksNavigator.MoveToBookmark(bookmarkName);

using (var imageStream = await imageStorageFile.OpenStreamForReadAsync())
{
    var pic = (WPicture)bookmarksNavigator.InsertParagraphItem(
        ParagraphItemType.Picture);
    pic.LoadImage(imageStream);
    pic.TextWrappingStyle = TextWrappingStyle.Inline;
}

I couldn't find any documentation on the supported image file formats. I guess it should work as long as the format is supported natively by Word. I didn't have any problems using any of the common file types. You will probably want to scale the image after inserting it to keep the document layout intact:

var scale = desiredHeight / pic.Height * 100f;
pic.HeightScale = scale;
pic.WidthScale = scale;

Keep in mind that the image size is defined in points just like font sizes.

Get notified when a new blog post is published (usually every Friday):

If you're looking for online one-on-one mentorship on a related topic, you can find me on Codementor.
If you need a team of experienced software engineers to help you with a project, contact us at Razum.
Copyright
Creative Commons License