Inserting images with apps for Office
Hi! I'm Gareth Pinto, a Program Manager on the Office Solutions Framework team working on the new apps for Office platform. You've heard a lot about our new platform goals, vision, architecture, and strategy from previous posts, and I hope it's inspired many app ideas of your own! With today's post, I'm going to describe a simple scenario-based task that may be applicable to many apps you hope to build: inserting images with apps for Office. I'll cover two ways of inserting images and a few tips and tricks to get you going.
Writing data into the document
With the JavaScript API for Office, you can write content into documents using the setSelectedDataAsync method. This method provides multiple coercion types for setting different types of data. Two coercion types that are unique to Word this release are HTML and Office Open XML (OOXML); these are the coercion types that can be used for inserting an image. When using setSelectedDataAsync, a required parameter is data, and for either of these coercion types, the data parameter should be a string of HTML or OOXML. Word automatically interprets and displays the data according to the coercion type.
Inserting images with HTML
In HTML, images are defined using the <img> tag. There are multiple (optional) attributes that you can use to customize the look of your image (alignment, border style, and so on). The attribute we are most concerned with is the src (source) attribute; src specifies the URL of where the image we want to insert is stored.
Here's a simple function to set an image via HTML:
function setHTMLImage(imgHTML)
{
Office.context.document.setSelectedDataAsync(
imgHTML, { coercionType: "html" },
function (asyncResult) {
if (asyncResult.status == "failed") {
write('Error: ' + asyncResult.error.message);
}
});
}
In the above function, imgHTML is a string of HTML that represents the image. For example;
var imgHTML = "<img " +
"src='https://i.msdn.microsoft.com/fp123580.AppHome2(en-us,MSDN.10).png'"
+ " alt ='apps for Office image' img/>";
sets the following image into your document:
It's as simple as that!
Set data via OOXML in Word
Office Open XML (OOXML) is an XML-based file format for representing documents, workbooks, presentations, and all the various objects and data structures within them.
Here's the equivalent function to set an image via OOXML:
function setOOXMLImage(imgOOXML) {
Office.context.document.setSelectedDataAsync(
imgOOXML, { coercionType: "ooxml" },
function (asyncResult) {
if (asyncResult.status == "failed")
{ write('Error: ' + asyncResult.error.message); }
});
}
Similar to the previous example, imgOOXML is a string of OOXML that represents the image. In OOXML, an image can be defined using the pic(picture) element. The following snippet of OOXML shows a closer look at this element:
<pic:pic xmlns:pic="https://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:nvPicPr>
<pic:cNvPr id="1" name="Picture.png"/>
<pic:cNvPicPr/>
</pic:nvPicPr>
<pic:blipFill>
<a:blip r:link="rId4"/>
<a:stretch>
<a:fillRect/>
</a:stretch>
</pic:blipFill>
<pic:spPr>
<a:xfrm>
<a:off x="0" y="0"/>
<a:ext cx="1975777" cy="1975777"/>
</a:xfrm>
<a:prstGeom prst="rect">
<a:avLst/>
</a:prstGeom>
</pic:spPr>
</pic:pic>
A child element of pic is blipFill (picture fill), and within the blipFill element, you can see that blip (picture) is defined as a link to relationship "rId4". As you can see in the following snippet, that relationship is of type "image" and has a target equal to the image URL: https://i.msdn.microsoft.com/fp123580.AppHome2(en-us,MSDN.10).png. Without getting into more OOXML specifics, here is the entire chunk of OOXML that represents the image:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?mso-application progid="Word.Document"?>
<pkg:package xmlns:pkg="https://schemas.microsoft.com/office/2006/xmlPackage">
<pkg:part pkg:name="/_rels/.rels"
pkg:contentType=
"application/vnd.openxmlformats-package.relationships+xml"
pkg:padding="512">
<pkg:xmlData>
<Relationships
xmlns="https://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type=
"https://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument
" Target="word/document.xml"/>
</Relationships>
</pkg:xmlData>
</pkg:part>
<pkg:part pkg:name="/word/_rels/document.xml.rels"
pkg:contentType="application/vnd.openxmlformats-package.relationships+xml"
pkg:padding="256">
<pkg:xmlData>
<Relationships
xmlns="https://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId4" Type=
"https://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
Target="https://i.msdn.microsoft.com/fp123580.AppHome2(en-us,MSDN.10).png"
TargetMode="External"/>
</Relationships>
</pkg:xmlData>
</pkg:part>
<pkg:part pkg:name="/word/document.xml" pkg:contentType=
"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"
>
<pkg:xmlData>
<w:document mc:Ignorable="w14 w15 wp14" xmlns:wpc=
"https://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:r=
"https://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:m="https://schemas.openxmlformats.org/officeDocument/2006/math"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:wp14="https://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"
xmlns:wp= "https://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:w="https://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:w14="https://schemas.microsoft.com/office/word/2010/wordml"
xmlns:w15="https://schemas.microsoft.com/office/word/2012/wordml"
xmlns:wpg= "https://schemas.microsoft.com/office/word/2010/wordprocessingGroup"
xmlns:wpi= "https://schemas.microsoft.com/office/word/2010/wordprocessingInk"
xmlns:wne="https://schemas.microsoft.com/office/word/2006/wordml"
xmlns:wps= "https://schemas.microsoft.com/office/word/2010/wordprocessingShape">
<w:body>
<w:p>
<w:bookmarkStart w:id="0" w:name="_GoBack"/>
<w:bookmarkEnd w:id="0"/>
<w:r>
<w:rPr>
<w:noProof/>
</w:rPr>
<w:drawing>
<wp:inline distT="0" distB="0" distL="0" distR="0">
<wp:extent cx="1958454" cy="1958454"/>
<wp:effectExtent l="0" t="0" r="0" b="0"/>
<wp:docPr id="1" name="Picture.png"/>
<wp:cNvGraphicFramePr>
<a:graphicFrameLocks noChangeAspect="1" xmlns:a=
"https://schemas.openxmlformats.org/drawingml/2006/main"/>
</wp:cNvGraphicFramePr>
<a:graphic xmlns:a="https://schemas.openxmlformats.org/drawingml/2006/main">
<a:graphicData uri="https://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:pic xmlns:pic=
"https://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:nvPicPr>
<pic:cNvPr id="1" name="Picture.png"/>
<pic:cNvPicPr/>
</pic:nvPicPr>
<pic:blipFill>
<a:blip r:link="rId4"/>
<a:stretch>
<a:fillRect/>
</a:stretch>
</pic:blipFill>
<pic:spPr>
<a:xfrm>
<a:off x="0" y="0"/>
<a:ext cx="1975777" cy="1975777"/>
</a:xfrm>
<a:prstGeom prst="rect">
<a:avLst/>
</a:prstGeom>
</pic:spPr>
</pic:pic>
</a:graphicData>
</a:graphic>
</wp:inline>
</w:drawing>
</w:r>
</w:p>
<w:sectPr>
<w:pgSz w:w="12240" w:h="15840"/>
<w:pgMar
w:top="1440"
w:right="1440"
w:bottom="1440"
w:left="1440"
w:header="720"
w:footer="720"
w:gutter="0"/>
<w:cols w:space="720"/>
<w:docGrid w:linePitch="360"/>
</w:sectPr>
</w:body>
</w:document>
</pkg:xmlData>
</pkg:part>
</pkg:package>
This results in the same image being set into the document:
As you can see, HTML and OOXML both provide sufficient methods for inserting images. Is there a benefit to one over the other? Yes! If you are after basic insertion and are comfortable with HTML/JavaScript, using coercion type HTML provides the simplest solution. But, although more complex, consider the following benefits that coercion type OOXML may offer (not limited to just image insertion):
· Familiarity –OOXML is an ISO standard and Word also natively understands OOXML, both of which result in very reliable data import/export that is more predictable than HTML. Also, many of you may already be working with OOXML through your existing Office solutions, enabling you to re-use code and expertise.
· Text Wrapping – By default, setSelectedDataAsync writes content with an inline text wrap. If you want to insert an image with a behind text, in front of text, or any other type of text wrap, you can achieve this with OOXML.
· Rich Formatting – Picture Tools in Word enable you to add additional formatting such as artistic effects, styling, borders, and much more. If you want to take advantage of some of this available functionality and customize the images you insert, you can achieve this using OOXML.
· Document Snippets – You can design any document snippet completely in Word, save the OOXML of that snippet, and re-use that snippet through your app (for example, a company logo, a bibliography, unique shapes, smart art, and so on).
Those are just a few examples, but there are many other options with OOXML that you can try for yourself. Here are some links to help you learn more about OOXML:
· Zeyad Rajabi’s Open XML SDK Blog Map
· Standard ECMA-376: Office Open XML File Formats
Tip: if you're not an OOXML pro (myself included!), try using the getSelectedDataAsync method with coercion type OOXML. Insert an image (or any content), add formatting and layout options that you are interested in, and (using getSelectedDataAsync) you can retrieve the OOXML. Now you've got the exact OOXML structure you need to write your custom formatted data!
Inserting images in other Office Clients
The two techniques shown above are currently available only in Word, but you may want your app to also work in Excel or PowerPoint. Unfortunately, not all coercion types are available in the other apps just yet. One option is to display the image inside your app, and instruct the end user to manually copy it into their document. This isn't the best user experience, but the more important pattern that I want to point out to you is that you can build your app agnostic of the host application it is being run in. This can be done by checking what coercion types (or other methods) are supported during run time. You can check whether a specific coercion type is supported by doing the following:
if (Office.CoercionType.Ooxml) {
// Code to run if true.
} else {
//Fallback code to run if false.
}
Using this pattern, your app can provide a workaround and/or limited experience if the full functionality is not possible. This gives you the benefit of having your app run in multiple Office host applications, opening it up to more users and scenarios, albeit with a less than ideal experience—a tradeoff worth considering. Also, by using this pattern, when the capability is enabled in the other Office applications, your app will support it right away without you having to update it.
Thanks for reading! I hope this post has shown you that, through the JavaScript API for Office, image insertion is simple and easy to achieve yet still powerful enough to provide complex, customized data-formatting capabilities. Good luck with your development, I'm looking forward to seeing more of your apps hit the Office Store soon!
Best regards,
Gareth Pinto
Comments
Anonymous
December 05, 2012
Gareth, Do both of these techniques assume the end user has access to the internet? I am concerned that if I embed an img into my app and the user goes offline, then they won't be able to see that image anymore. What are your thoughts on truly embedding the image in the app without relying on the fact that the end user might have internet access in the future?Anonymous
December 05, 2012
Gareth, Another question on images. My app creates an html 5 base64 encoded image. However, that cannot be inserted into Word. Seems like the <img tag in word only understands images that have a src reference to a web area. However, html5 only allows for the creation of base64 encoded images when converting a canvas to an image. Any thoughts on how to embed that into Word from the task pane app?Anonymous
December 06, 2012
Good questions Greg... the blog entry explains 2 ways of inserting the image a. using html - this way requires internet connectivity because the src element of image is pointing to a resource on the web. That means, in a disconnected scenario the image will not appear. b. using OOXML. this method actually embeds the image in the document, the provided OOXML includes the base 64 representation of the image, hence does not depend on an internet connection. Gareth describes a technique on how to get the OOXML using the getSelectedDataAsync method to get an OOXML sample image, just make sure to replace the base64 with the one from your image and use it in the setSelectedDataAsync method as the data parameter and make sure to use the CoercionType OOXML. hope this helps.. thanksAnonymous
December 08, 2012
The comment has been removedAnonymous
January 18, 2013
hi, can you please tell how to get multiple auto shapes in selection as getSelectedDataAsync() takes only text as coercion Type for PowerPointAnonymous
January 30, 2013
Hi Gareth, I insert image with OOXML by according to the blog, but I can not implement the inserting image by OOXML way, can you share a code for me?Anonymous
March 05, 2013
If someone's looking for a way to embed the image (much as Greg mentioned above), see my reply on social.msdn.microsoft.com/.../2a2b32dc-aca3-425c-9c21-4122087e997f for the complete OOXML chunk. Hope this helps someone!Anonymous
February 07, 2015
Hi Gareth, I recently discovered a nifty add-in for Excel named Picture Manager for Excel (found at http://doality.com) which accurately imports by means of embedding as well as exports images in mass to/from spreadsheets and sizes automatically within cells.Anonymous
July 31, 2015
hello Sir nice tuts but please guide me for the power points images insertions and skypeid zaid.ahmadkhanAnonymous
August 03, 2015
function ImageInsertMsWord(id) { var images = $('#teamhidden' + id + '').val(); var mydoaldiv = ''; var imageinsert = $('#teamlargehidden' + id + '').val().trim(); mydoaldiv = mydoaldiv + '<div style="padding:10,10,10,10" > <img style="margin-top:10px" src="' + images + '" height="200" width="150px" /><input type="button" value="Insert Image" id="setDataBtna" class="btn-primary" /> <input id="imagehiddenval" type="hidden" value=' + images + '></div>'; $('#imagediv').html(''); $('#imagediv').html(mydoaldiv); $('#setDataBtna').click(function () { var imgHTML = "<img " + "src='" + imageinsert + "'" + " alt ='apps for Office image' img/>"; Office.context.document.setSelectedDataAsync( imgHTML, { coercionType: "html" }, function (asyncResult) { if (asyncResult.status == "failed") { write('Error: ' + asyncResult.error.message); } }); }); } but i want to insert images like we insert text into power points all given methods for power is returning undefined thing except text . please guide me or help me My mail ID khan_zaid24@hotmail.com skype ID zaid.ahmadkhan