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:

Image to insert into a 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:

Image to insert into a 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 FormattingPicture 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

· OpenXMLDeveloper.org

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