SharePoint now accessible via the Microsoft Graph beta

Last week at Ignite it was announced that finally Microsoft was bringing O365 SharePoint access to the Microsoft graph as an API. This is a huge deal for those of us who want to use O365 as a platform and develop engaging applications for customers. In my case for Office Add-ins this is great because it reduced the number of OAuth hoops I have to jump through and manage to get the data I want.

Here is a link to the documentation: Working with SharePoint sites in Microsoft Graph and a quick example.

NOTE: this is beta and will change – this is purely a demonstration of what is possible today (Oct 2016) and not to be used as future reference.


Using the graph explorer demo I am able to bring up content from my default SharePoint site very easily

Here is my copper site within my SharePoint tenant


and here it is referenced from the graph API{site-id}


here is the API response of the lists{site-id}/lists


and here is a reference to the documents in the Shared Documents folder{site-id}/lists/{list-id}/items


How cool is that !!!!!


Microsoft MVP for Office Development

This weekend I was thrilled to receive an email from Microsoft announcing that I had been recognized as a Microsoft Most Valuable Professional (MVP) in the Office Development technical community. This is a very natural evolution of my journey over the last two years since I branded out from nearly 20 years in IBM Domino. As I said about the xomino365 blog it was all about taking my skills on tour and seeing where it took me. While that blog served it’s purpose and I have come back to exclusively, I am very content with the place it took me.

I wanted to take a moment to thank those people who nominated me (that I am aware of): Theo, John, Rob, Michael, Ren? and I am sure others – I really appreciate your support and belief in me.

I also wanted to thank Lisa Anderson (MVP wrangler for the mid-west) and Simon Jaeger (MS developer advocate) for their encouragement and support. They helped me know I was on the right path and are now responsible for what they helped create😉

Finally I wanted to thank John Quirk and @PSCGroup who have given me a job and platform to allow me to do what I do best. I really love my job and the people I work with.

This (as always) is going to be fun🙂


Thanks again


Speaking at Dreamforce next week :)

Next week I will be in San Fransisco for the Dreamforce conference – this will be the biggest conference I have attended, never mind spoken at and I am really excited to go🙂

If anyone is going to be around at the conference or in the area – ping me on Twitter @MarkyRoden – be good to meet up🙂


Unleashing the power with Salesforce and Microsoft Office 365 Add-ins


Moscone West, Developer Lightning Theater

THANK YOU NOTES IN 9 !!!!!!!!!!!!!

Once upon a time there was a guy who worked for a trucking company and he decided that he needed to learn this new XPages thing – and he figured why not share what I am doing? That was over 7 years ago and it grew into the largest single video repository in the history of IBM Domino. Dave Leedy is coming to the end of his XPages-casting career and is hanging up his cleats in this arena. Not only did Notesin9 lead to more opportunities for Dave, it also helped many many other people.

Dave will not admit it, but site has helped more people be successful that he could have ever imagined,

Dave and Notesin9 are a huge reason for my personal success in the last few years and I know I am not alone. Dave’s encouragement and the hosting costs he provided out of his own pocket provided a platform for my success unmatched in my professional career. I owe him a huge debt of thanks personally and many others do too.

So a few friends (44 people!!) and I got together and decided it would be cool to create something memorable that Dave could relate to and I really hope it gives you some idea of the love……

So today we are releasing the unofficial-official #thanksnotesin9 video. I hope you enjoy it. Share it, trend it, it’s worth it to everyone in the IBM Domino community.

I know there are many others who would like to contribute but we had to keep this on the quiet and had to be completed eventually. If you have a thanks video you want to make then link it in the comments below. The more the merrier🙂





make sure you watch it to the end😉

Saving a word document directly from an Office Add-In into

In this article I will demonstrate and discuss how to programmatically save a Word document directly into Salesforce.


In previous articles we have looked at how to programmatically interact with a Word document from within an Office Add-In. In this case we will use the Office JavaScript API to access the file as a binary string and then convert it into a format compatible with

Turning your word document into a binary

This article in the Office dev center details how to Get the whole document from an add-in for PowerPoint or Word. We will use the bulk of that article up to the point where we send the slice. We are going to look at a modified sendSlice() function. The article details how you can access the binary contents of the word document, but falls short when it comes to getting the base64 encoded version of the file to be submitted to an external site. This is the complicated part !

Getting the right format for Salesforce

Unfortunately the salesforce documentation is not based around using JavaScript to access the REST APIs. It is based around using curl commands in UNIX. The sample page for Inserting or updating Blob Data explains how to upload a multipart message which includes both the meta-data values and the binary data for the file. For the record they also neglect to provide any guidance on how to get the binary of the file….!

Using the code posted on this stackoverflow post  we are able to turn a binary string into the necessary format to send the file to salesforce.

The final sendSlice() function is shown below. The significant thing to note is that the initial file must be sent to the ContentVersion sobject. Because this is a new document a parentId is not necessary and a ContentDocumentId is created. In a future article we will look at how to then associate this new file attachment is an existing object.

function sendSlice(slice, state) {
  updateStatus("In sendSlice");
  var data =;

  // If the slice contains data, create an HTTP request.
  if (data) {

    // Encode the slice data, a byte array, as a Base64 string.
    // NOTE: The implementation of myEncodeBase64(input) function isn't
    // included with this example. For information about Base64 encoding with
    // JavaScript, see

    var u8 = new Uint8Array(data);
    var b64encoded = btoa(String.fromCharCode.apply(null, u8));

    var objectData = {
      "Description": "Demo Upload Directly from Word",
      "Title": "sample.docx",
      "ReasonForChange": "Initial Upload",
      "PathOnClient": "sample.docx"

    var boundary = 'boundary_string_' +;
    var attachmentContentType = 'application/octet-stream';

    // Serialize the object, excluding the body, which will be placed in the second partition of the multipart/form-data request
    var serializedObject = JSON.stringify(objectData);

    var requestBodyBeginning = '--' + boundary
        + '\r\n'
        + 'Content-Disposition: form-data; name="entity_attachment";'
        + '\r\n'
        + 'Content-Type: application/json'
        + '\r\n\r\n'
        + serializedObject
        + '\r\n\r\n' +
        '--' + boundary
        + '\r\n'
        + 'Content-Type: ' + attachmentContentType
        + '\r\n'
        + 'Content-Disposition: form-data; name="VersionData"; filename="filler"'
        + '\r\n\r\n';

    var requestBodyEnd =
        + '--' + boundary + '--';

    // The atob function will decode a base64-encoded string into a new string with a character for each byte of the binary data.
    var byteCharacters = window.atob(b64encoded);

    // Each character's code point (charCode) will be the value of the byte.
    // We can create an array of byte values by applying .charCodeAt for each character in the string.
    var byteNumbers = new Array(byteCharacters.length);

    for (var i = 0; i < byteCharacters.length; i++) {
      byteNumbers[i] = byteCharacters.charCodeAt(i);

    // Convert into a real typed byte array. (Represents an array of 8-bit unsigned integers)
    var byteArray = new Uint8Array(byteNumbers);

    var totalRequestSize = requestBodyBeginning.length + byteArray.byteLength + requestBodyEnd.length;

    var uint8array = new Uint8Array(totalRequestSize);
    var i;

    // Append the beginning of the request
    for (i = 0; i < requestBodyBeginning.length; i++) {
      uint8array[i] = requestBodyBeginning.charCodeAt(i) & 0xff;

    // Append the binary attachment
    for (var j = 0; j < byteArray.byteLength; i++, j++) {
      uint8array[i] = byteArray[j];

    // Append the end of the request
    for (var j = 0; j < requestBodyEnd.length; i++, j++) {
      uint8array[i] = requestBodyEnd.charCodeAt(j) & 0xff;

    //Create the new file in Salesforce
    var url = ""

    return $.ajax({
      method: "POST",
      url: url,
      processData: false,
      data: uint8array.buffer,
      headers: {
        "Content-Type": 'multipart/form-data' + "; boundary=\"" + boundary + "\"",
        "Authorization": "Bearer " + app.getCookie(app.addinName)
    }).error(function (data) {
      updateStatus("FAIL: " + JSON.stringify(data))
    }).success(function (data) {
      updateStatus("Success creating ContentVersion: " +




In this article we have seen an example of how we can extend the functionality of an Office Add-In to access the binary data of a word document and then save it to a cloud provider (in this case Salesforce).


Adding an attachment to an opportunity using Salesforce REST APIs

In this article I will show the simple and straight forward method for adding an attachment to a Opportunity using the Salesforce REST APIs.


This article is written as a summation of a frustrating couple of days trying to discern the Salesforce REST API documentation. I started with the Insert or update Blob page. With all the examples based on UNIX commands it made it very difficult to figure out how to do this using client side JavaScript.

Eventually I realized there was a link to the SObject Basic Information help page and SObject Rows help page. Using a combination of all three pages of information as a reference I was able to figure out how to do what I needed to. I needed to write it up as I will likely forget about it😉

Adding attachments

To add an attachment into Salesforce you have to get the base64 encoded string thereof and submit it as an Attachment Object, referencing the parentId of the Opportunity.

In my example I have an opportunity Id = 00658000004kGVRAA2. note that there are no attachments.


Using the combination of the three help documents I was able to figure out that sending the base64 encoded attachment to the opportunity is nothing more complicated that constructing the following

var root = ""

var url = root+"services/data/v37.0/sobjects/Attachment"

var data = {
  "Name" : "demoAttachment.pdf",
  "Body": "Base64Encoded Attachment",
  "parentId": "00658000004kGVRAA2" //the id of the opportunity

  url: url,
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer "+OAuthToken
  data: JSON.stringify(data)

When the POST is successful you will receive the new Id of the Attached file


The attachment appears on the opportunity


and we can download and open the file



The important part of this example is to understand that we are not creating an attachment from the opportunity. We are creating the attachment and associating itself with the opportunity. Trying to go at the opportunity and throw the attachment at it directly was a complete failure.