What is Office 365, really?

In my day-to-day dealings with people and organizations, there is a common confusion on the term “Office 365.” And that confusion is fed by a few common myths that I have heard repeated by some very smart people in those organizations. So, first, let me dismiss the myths…

  • The first one is that Office 365 is online, in the browser applications only… NO! Office 365 is NOT just Excel Online, Word Online, PowerPoint Online, Outlook Online, and OneNote Online.
  • And the second myth is that the desktop applications are getting deprecated… NO! Microsoft is NOT doing away with the installed desktop applications on Windows and Mac in favor of web based versions.

So let’s get to the question:

If Microsoft is not replacing Office with web versions, then what the heck is all this Office 365 and cloud stuff then?

Primarily, Office 365 is the name of the subscription. You no longer buy the Office applications on disks and install them, then buy the next version, etc. With the subscription you always get the newest version (and much more). As you will read from the link above, there are lots of FAQ’s and other information that explain how this works.

So Excel Online, ET AL. is PART of the Office 365 subscription based platform. Office 365 still includes the traditional Microsoft Office desktop applications on the PC/Windows or the Mac. And they are not going anywhere. When you hear that your organization is moving to Office 365 it does not mean you will ONLY be accessing Office from a web browser.

Office 365 is really Office anywhere, on any device. For example, Office 365 also includes applications on iPhone, iPad, and Android. And it is not just the traditional applications. There are incredible tools such as Forms, Sway, Teams, and for developers the Graph API. It also shifts workloads like Exchange Server for mail and SharePoint server for document management from local IT servers to servers run by Microsoft in the cloud.

So when you hear Office 365, DO NOT THINK GOOGLE DOCS. wlEmoticon-smile.png The online versions of Office are only there to provide an additional avenues to access Office from anywhere, on any device. Per the Office 365 website:

Works across multiple devices

Get the fully installed Office apps on multiple PCs, Macs, tablets, and mobile devices (including Windows, iOS, and Android).

They are not as fully featured and as such you really need to consider when you might use them over using the traditional Microsoft Office desktop applications. Per this site (my emphasis added):

Office for the web (formerly Office Web Apps) opens Word, Excel, OneNote, and PowerPoint documents in your web browser. Office for the web makes it easier to work and share Office files from anywhere with an internet connection, from almost any device. Microsoft Office 365 customers with Word, Excel, OneNote, or PowerPoint can view, create, and edit files on the go. …

The following tables compare Office for the web feature capabilities to feature-rich Microsoft Office desktop apps.

So, if you like your Excel just the way it is, installed on your scientific workstation with a bazillion gigabytes of RAM, you can still run it there if you move to Office 365. What you get with the traditional Office applications is more frequent, seamless and automatic updates from the web. Per the Office 365 website:

Monthly Updates

Get the latest features and capabilities with fully installed and always up-to-date versions of Outlook, Word, Excel, PowerPoint for Windows or Mac, OneNote (features vary), Teams, and Access and Publisher (PC only).

Hopefully, this has helped clear up and dispel the myths. And when you go back to the smart person that has told you otherwise, and continues to insist and tell you otherwise, please send them here. wlEmoticon-hotsmile.png

OfficeJS.dialogs Updated (v1.0.5)

I have been working hard on my OfficeJS.Dialogs library and just published version 1.0.5. You can get it from NPM and GitHub. See my previous post for more information on how to do this.

I have added a few new features:

  • A simple Alert.Show() method that displays a simple OK box. For those times you want to just simply pop up a quick notification to the user.
  • A Progress.Show() that displays a progress bar. This allows for you to show the progress bar and then issue Progress.Update() to move the progress bar along. When you are done you call Progress.Complete().
  • A Wait.Show() dialog that will show an indeterminate spinner. This form will remain up until you issue a Wait.CloseDialog().
  • New UpdateMessage() and Update() methods were added to the MessageBox. This was done to allow you to quickly ask a lot of questions of the user in one instance of the dialog, without giving the user back to the application for a second while the new dialog is rendered. UpdateMessage() will just update the message but keep all the buttons the same, but you will specify a new callback. Update() will allow you to fundamentally change all the settings the MessageBox (buttons, icon, caption, text and all), plus a new callback function.
  • Behind the scenes I made some improvements/bug fixes:
    • If you try to show two dialogs too quickly, nothing will happen. So I added a half-second delay between dialog displays to make sure you never get an overlap.
    • You will get an error message in your callback if more than one dialog is attempted to be opened at once.
    • “Window Messaging” has been setup with Progress and MessageBox to allow the parent and the dialog to pass messages back and forth. It involves using setTimeout().

For those interested in the last item, here is what that look like:

[code lang=”javascript” collapse=”true” title=”click to expand if the embedding below is not visible.”]
/**
* Handles messages coming from the parent
*/
function startMessageHandler() {
setTimeout(function() {
var message = localStorage.getItem("dialogMessage");
localStorage.setItem("dialogMessage", ""); // clear the message
if(message !== undefined && message !== null && message != "")
{
var msg = JSON.parse(message);
if(msg.message == "update") {
// update the form
updateForm(msg.settings);
} else if(msg.message == "close") {
// do nothing special here
return; // stops the message pump
} else if(msg.message == "progress") {
if(msg.settings.Number > 100) return;
$("#bar").prop("value",msg.settings.Number);
}
}
startMessageHandler(); // call again
}, 0);
}
[/code]


/**
* Handles messages coming from the parent
*/
function startMessageHandler() {
setTimeout(function() {
var message = localStorage.getItem("dialogMessage");
localStorage.setItem("dialogMessage", ""); // clear the message
if(message !== undefined && message !== null && message != "")
{
var msg = JSON.parse(message);
if(msg.message == "update") {
// update the form
updateForm(msg.settings);
} else if(msg.message == "close") {
// do nothing special here
return; // stops the message pump
} else if(msg.message == "progress") {
if(msg.settings.Number > 100) return;
$("#bar").prop("value",msg.settings.Number);
}
}
startMessageHandler(); // call again
}, 0);
}

view raw

setTimeout.js

hosted with ❤ by GitHub

Here is an example of how to use the Progress dialog. The method signature is like this:

Progress.Show( [message], [start], [max], [completeCallback], [cancelCallback] )

  • The message is the message the user see’s when the dialog is opened.
  • The start is the number you want the progress bar to start at. Usually this should just be zero (0).
  • The max is the number you want the Progress bar to end at. Usually this should be 100. But it can be any number you want. If you have 5 steps to perform in the background while this dialog is up, you can set this to 5.
  • The completeCallback is your callback function to be called when your code calls the Progress.Compelte().
  • The cancelCallback is what gets called when the user presses the Cancel button on the form.

By itself, this will do nothing. You will have to call the Progress.Update() command in order to move the progress bar, or update the message to the user. Here is the method signature for the Update method:

Progress.Update( [amount], [message] )

  • The amount is how much you want the progress bar to move. If you do not specify an amount, an amount of 1 is assumed.
  • The message is a new message to provide the progress bar. If you want to update the message and do not want to increment the progress bar, specify an amount of zero (0).

Once you are all done with the Progress dialog, you issue a Progress.Complete() call. There are no parameters to it. Once called, your completeCallback in the Progress.Show() call will then be executed.

Here is an example:

[code lang=”javascript” collapse=”true” title=”click to expand if the embedding below is not visible.”]
// reset first to make sure we get a fresh object
Progress.Reset();
// display a progress bar form and set it from 0 to 100
Progress.Show("Please wait while this happens…", 0, 100, function() {
// once we are done – when your code
// calls Progress.Complete()
Alert.Show("All done folks!");
}, function() {
// this is only going to be called if the user cancels
Alert.Show("The user cancelled");
});
doProgress();

function doProgress() {
// increment by one, the result that comes back is
// two pieces of information: Cancelled and Value
var result = Progress.Update(1);
// if we are not cancelled and the value is not 100%
// we will keep going, but in your code you will
// likely just be incrementing and making sure
// at each stage that the user has not cancelled
if(!result.Cancelled && result.Value <= 100) { setTimeout(function() { // this is only for our example to // cause the progress bar to move doProgress(); },100); } else if(result.Value >= 100) {
Progress.Compelte(); // done
}
};
[/code]


// reset first to make sure we get a fresh object
Progress.Reset();
// display a progress bar form and set it from 0 to 100
Progress.Show("Please wait while this happens…", 0, 100, function() {
// once we are done – when your code
// calls Progress.Complete()
Alert.Show("All done folks!");
}, function() {
// this is only going to be called if the user cancels
Alert.Show("The user cancelled");
});
doProgress();
function doProgress() {
// increment by one, the result that comes back is
// two pieces of information: Cancelled and Value
var result = Progress.Update(1);
// if we are not cancelled and the value is not 100%
// we will keep going, but in your code you will
// likely just be incrementing and making sure
// at each stage that the user has not cancelled
if(!result.Cancelled && result.Value <= 100) {
setTimeout(function() {
// this is only for our example to
// cause the progress bar to move
doProgress();
},100);
} else if(result.Value >= 100) {
Progress.Compelte(); // done
}
};

That example also uses the new Alert dialog. This one is very simple:

Alert.Show ( [message] )

This next example uses the new Wait dialog, which is much simpler to implement. Here is the method signature:

Wait.Show( [message], [showCancel], [cancelCallback] )

  • The message is the message you want to show the user. If you specify null, it will appear as simply “Please wait…”
  • The showCancel flag if set will allow the user to see a Cancel button.
  • The cancelCallback function is only valid if the showCancel option is true. When the user presses cancel, this function gets called.

When you are ready to close the Wait dialog, you issues a Wait.CloseDialog(). Here is an example:

[code lang=”javascript” collapse=”true” title=”click to expand if the embedding below is not visible.”]
Wait.Show(null, true, function() {
Alert.Show("The user cancelled.");
});
setTimeout(function(){
Wait.CloseDialog();
Alert.Show("Done!");
}, 15000);
[/code]


Wait.Show(null, true, function() {
Alert.Show("The user cancelled.");
});
setTimeout(function(){
Wait.CloseDialog();
Alert.Show("Done!");
}, 15000);

If you have some suggestions for some things you would like to see added to this library, please add a comment below or reach out to me on LinkedIn or Twitter. Some ideas I will be working on:

  • Allow you to call another dialog type without having the close the dialog.
  • A selection dialog, where you have a dropdown list of a listbox where you wan select (or multi-select) items.
  • An option to resize forms.
  • An option to use the message handler in your own custom form – minimal code

Creating a Loader Add-in (Master Add-in)

I have now helped about half a dozen customers over the last 3 years to perform this very same task. In each case the scenario is the same:

  • They have documents that are very specific to their system
  • They want to create an add-in to assist with the management of these documents.
  • They only want the add-in to load when one of their document is opened.
  • BONUS: They also want to remove other add-ins
  • BONUS: They would like a pristine instance of Word or Excel.

There are several methods to accomplish each of these tasks. But the one I find is easiest to maintain is what I call the “Master Add-in” approach.

In the “Master Add-in” you essentially attach one event: DocumentOpen or WorkbookOpen. You place code in the event to detect whether it is a document you care about. This can be done in several ways:

  • You can look at the path where the file came from.
  • You can look at the name of the file, if there is a specific naming convention you follow.
  • Or, you can tag he document with Document Properties or Custom Xml Parts.

Once you have identified that it is a document you care about you follow this basic process:

  • Get the path to the file being open and store it.
  • Close the workbook or document being passed into the Open event.
  • Create a new Instance of Word or Excel.
  • Iterate through the COM Add-ins collection and the Add-ins collection and disable everything you do not want running. This includes disabling the Master Add-in as you do not want it running for the next parts.
  • Locate your COM Add-in in the collection and set Connect = true.
  • Open the document or workbook from the application object.

You will now have two instances of Excel or Word open. One that the user was originally working with which has the Master Add-in loaded and then the new one that is customized with your specific add-in and only your add-in.

This is useful for when you have multiple versions of your system and you can update the Master to recognize which version to launch.

Getting this to work just right is sometimes a challenge and you have to be careful not to disable all the add-ins for all instances. I have a few customer examples that I have built and will work on cleaning them up. I will combine the best parts and will write a new entry in the future which will walk you through creating one.