Partilhar via


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

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.. thanks

  • Anonymous
    December 08, 2012
    The comment has been removed

  • Anonymous
    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 PowerPoint

  • Anonymous
    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.ahmadkhan

  • Anonymous
    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