Programmatically Inserting an image from an O365 Add-In into your Word 2016 document

In this article I will demonstrate how to convert a web based image, displayed in an Add-In, into a base64 encoded string. With that I will then insert it into a Word document, directly from the Add-In.

Introduction

In the previous article I showed how to manually insertInlinePictureFromBase64 an image into a Word 2016 document. In this article I will demonstrate how to convert and existing web based image into base64 encoded string and then insert it.

HTML5 canvas element

Using the HTML5 canvas element we can easily convert an image to base64 using the canvas.toDataURL() method. The following code is a simple example of how to get an image from within the Add-In, convert it and insert it.

NOTE

The canvas.toDataURL() method will trigger a Security Alert if the image is not hosted in the same domain as the Add-In.

//create a canvas element 
var c = document.createElement("canvas"); 
var ctx = c.getContext("2d"); 
var img = document.getElementById("preview"); 
ctx.drawImage(img, 10, 10); 
//create the base64 encoded string and take everything after the comma
//format is normally data:Content-Type;base64,TheStringWeActuallyNeed
var base64 = c.toDataURL().split(",")[1];

//insert the TEXT o fthe base64 string into the word document as text
// Run a batch operation against the Word object model.
Word.run(function (context) {

    // Create a proxy object for the document body.
    var body = context.document.body;

    // Queue a commmand to insert HTML in to the beginning of the body.
    body.insertHtml(base64, Word.InsertLocation.start);

    // Synchronize the document state by executing the queued commands,
    // and return a promise to indicate task completion.
    return context.sync().then(function () {
        console.log('HTML added to the beginning of the document body.');
    });
})
.catch(function (error) {
    console.log('Error: ' + JSON.stringify(error));
    if (error instanceof OfficeExtension.Error) {
        console.log('Debug info: ' + JSON.stringify(error.debugInfo));
    }
});

//Insert the image into the word document as an image created from base64 encoded string
Word.run(function (context) {

    // Create a proxy object for the document body.
    var body = context.document.body;

    // Queue a command to insert the image.
    body.insertInlinePictureFromBase64(base64, 'Start');

    // Synchronize the document state by executing the queued commands,
    // and return a promise to indicate task completion.
    return context.sync().then(function () {
        app.showNotification('Image inserted successfully.');
    });
})
.catch(function (error) {
    app.showNotification("Error: " + JSON.stringify(error));
    if (error instanceof OfficeExtension.Error) {
        app.showNotification("Debug info: " + JSON.stringify(error.debugInfo));
    }
});

As we can see from the image below – the image and text are inserted. There is 4 pages of text for what was originally a 6KB (SIX) image.
This is not a very quick process.

im1

im2

Conclusion

This is pretty slow programmatically and a copy and paste is just as effective. But, it can be done so you never know someone might find use for it in the future 🙂

Advertisements

Inserting a base64 encoded image into a Word 2016 document

In this article I will demonstrate the new Word JavaScript API method which can be used to insert a base64 encoded image into a Word 2016 document.

Introduction

In the latest version of Office 365 Word 2016 (May 2016) a new capability has been released “insertInlinePictureFromBase64”. The documentation so far is a little sparse but can be found here (http://dev.office.com/reference/add-ins/word/body) . The new method is part of the body object within the JavaScript API model. For more information on the version of Word you need to get this to work check out this link (Office add-in requirement sets).

Do you have the correct version?

I found this StackOverflow answer which gave code similar to the following to test to see if you have the correct version of the JavaScript API available.

Word.run(function (context) {
	// Create a proxy object for the document body.
	var body = context.document.body;
	// Queue a commmand to insert HTML in to the beginning of the body.
	if (Office.context.requirements.isSetSupported("WordApi", "1.2")) {
		body.insertHtml('<strong>"You have the right version"</strong>', Word.InsertLocation.start);
	} else {
	body.insertHtml('<strong>"You do not have the right version. This functionality requires Word with at least January 2016 update!! (check  builds 6568+)"</strong>', Word.InsertLocation.start);
	}
		// Synchronize the document state by executing the queued commands,
		// and return a promise to indicate task completion.
		return context.sync().then(function () {
			console.log('HTML added to the beginning of the document body.');
	});
})

I created a simple Add-In examples locally, containing a message DIV and some FirebugLite.

Inserting an image.

Taking one of the examples from the documentation page and modifying it slightly we can see the basics of how the insert will happen:

var img = '' //a base64 encoded string

// Run a batch operation against the Word object model.
Word.run(function (context) {

    // Create a proxy object for the document body.
    var body = context.document.body;

    // Queue a command to insert the image.
    body.insertInlinePictureFromBase64(img, 'End');

    // Synchronize the document state by executing the queued commands,
    // and return a promise to indicate task completion.
    return context.sync().then(function () {
        app.showNotification('Image inserted successfully.');
    });
})
.catch(function (error) {
    app.showNotification("Error: " + JSON.stringify(error));
    if (error instanceof OfficeExtension.Error) {
        app.showNotification("Debug info: " + JSON.stringify(error.debugInfo));
    }
});

As we can see from the code, what is happening is the the “context” of the Word document is being manipulated in memory and then “sync’ed” with the actual HTML managing the Word document. The “Word document” itself is not a webpage. It can handle HTML but it is not a web browser and is not capable of being manipulated directly from the Add-In. If this works we should see an image.

What is a base64 encoded string anyway?

Base64 is a group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation. The term Base64 originates from a specific MIME content transfer encoding.” (https://en.wikipedia.org/wiki/Base64)

If you look for examples of base64 encoded images on the web you can see something like this – https://css-tricks.com/examples/DataURIs/ which shows two ways of referencing an image using the encoded string. Firstly in CSS and secondarily as an image. View the source of the page

i2

i1

The “base64 encoded string” takes the form “data:”+ [content-type]+”;base64,” and then the actual string

data:image/gif;base64,R0lGODlhEAAQA……………

“data:”+”image/gif”+”;base64,”R0lGODlhEAAQA……………….”

I am not using the full string for the base64 encoded image in my code snippets, because it is unwieldy in the context of the blog post.

THIS IS THE REALLY IMPORTANT PART !!!!
In the case of insertInlinePictureFromBase64 the entire string does not work! You only use everything after the comma.
THIS IS THE REALLY IMPORTANT PART !!!!

In my case only the following is necessary

var img = ‘R0lGODlhEAAQA……

In Summary

As you can see from the image below when you put this all together inside your JavaScript you can insert images into your Word document..

i3

Using the Jellyfish image example (which is a really long text string)

i4

 

Conclusion

In this article we seen how the new body.insertInlinePictureFromBase64 method can be used with the Word API to insert an image into a word document. Particular attention has to be paid to the string being inserted for the image, it must not include the content-type or the data signifier.

In the next article we will look at how we can easily a base64 encoded image for ourselves programmatically in the context of an Add-In