As per my previous post, the thing I found most interesting was how Excel full client seems to fail if you configure your server .htaccess file to prevent caching. Well, I found out that my Outlook Send to Trello add-in actually had the same problem too. The Outlook client just happened to refresh this morning and my icon disappeared there too. In Office online it seems to work, but in the full client you cannot seem to force the client to NOT cache. I see my files all pulled down locally in the Wef folder and my concern is that when I update the add-in it will not go get the latest every time… I have actually seem and beat my head over this problem a few times. But the solution there for anyone working on a BETA site for example making changes and all of a sudden the full-client stops refreshing your updates, this is a good article to keep handy.
But when Wef strikes in production, I have found customers are not so excited to blow away this folder and find all their add-ins, preferences, stored cached credentials and other goodies for each and every add-in are gone. Ergo why I added the no-cahce to the .htacess. Oh well. 🙁
Also, just to share something else as I am delving more and more into publishing add-ins for real. As an Office Developer, in the traditional sense (aka boomer 😛, VBA/VSTO/COM), there are aspects of living in an HTML web world that I still learning (although this is an old one it comes up now and again because I forget something).
You have to worry about various attack vectors and sanitizing HTML strings. There are LOTS of libraries and solutions out there and Mozilla even has documented a possible standard supported in several browsers, but not all. It is a tricky thing because some sanitizers do too much or not enough, and then you also rely on a dependency which has now burned me more often than just owning things that might be a hundred lines of code for my own common library of goodies.
So, I have created my own based on various library implementations, and found the best option is to escape most of the stuff you find “injected” rather than remove it.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The important thing is that in the web world, anytime you take data from one service to another, or take input in a field, or grab input from some element on a page and insert it back into another element in your code, there is a hack waiting to happen if you do not sanitize.
I recently published a new Excel Add-in called “Excel Send to Trello.” It is a pretty nifty add-in that will take an Excel sheet full of names, descriptions, and dates and build a bunch of Trello Cards on a specific list in Trello for you. It is just a start (v1.0) and has many features to come based on popularity.
But when I submitted the add-in to AppSource they came back to me with an issue that I was not seeing. Specifically, that the icon on the Ribbon was showing the default add-ins image and not my icon. I did not see this on my “beta” test site that I was using but had sent them a link to my manifest with was right to my production published version. The issue it turns out after a lot of testing was the .htaccess on my production site and the ONLY difference was this line:
<IfModule mod_headers.c>
Header set Cache-Control "no-store, no-cache, must-revalidate"
</IfModule>
The problem it turns out is that Excel (full client) cannot read your icon without caching it. This works FINE in Excel Online. Oh well. So, I cannot prevent my add-in JS files from being cached which it turns out is a huge problem when I push an update it can take days/weeks for the Office application to expire its own cache. Unless someone know a way around this…
Anway, the way I discovered this was via sideloading the manifest pointing to my production site. And it also turns out I had forgotten how EASY Outlook makes sideloading. In Excel (full client) it is not that easy, because you do not have the option to point to your own manifest, except in Excel Online. Then I recall some work a colleague Marty Andren and I worked on many, many years ago, called the Web Add-in Side loader. And low and behold, it still works like a charm.
I was able to sideload in Excel using the command line tool, then I saw the problem. That is where I began the file-by-file comparison “Beta” to “Production” and found the difference mentioned above.
Anyway, it was an adventure, with a blast from the past! And keep an eye out, my new Excel Add-in will hopefully be published any day now.
While working on a customers proof of concept, we determined that we needed to know who the current user opening the add-in is. In most scenarios where there is a Store Add-in, you have the user log in. But we are in a enterprise environment, have an embedded taskpane and did not want to nag the user every single time they opened the document.
Outside of the BETA API set, there actually is not a way to do this in Word, Excel and PowerPoint. In the current BETA API (soon to be released), is the new Single sign-on (SSO) API. Detailed here:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sometimes you have multiple add-ins and you need to facilitate communication between them. For example, a common scenario I have heard is that you have:
A Content Add-in that displays something like a graph or an organization chart.
A Taskpane app that allows you to manipulate settings, upload and download data from a backend web service.
You need to be able to facilitate communication between the two so that when updates happen to one add-in, the other receives those updates. I recently worked on a proof of concept that helped prove how this can be done.
The solution is to use the Document as a communication medium. In the particular case we used CustomXMLParts in the document. Here is how it would work:
One add-in would need to send an update to the other, so it would write a CustomXMLPart with a specific namespace and a “context” (basically, I am the TaskPane communicating) to the document.
Both add-ins will have a window.setInterval() thread running to check the documents for CustomXMLParts in that given namespace.
The timer on the Content Add-in would fire, find the new customXMLPart from the taskpane, read the contents and then update itself as needed and finally, delete the CustomXMLPart.
Here is the code for the Content Add-in to look for the message from the TaskPane:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Next, here is the code in the Task Pane Add-in that will send the message for the content add-in to read:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
If you are just getting started with OfficeJS, then this post is for you. I will assume you have some understanding of what Office Web Add-ins are. However, there is one very basic point I will demonstrate in this tutorial:
An Office Web Add-In is simply a web site and an XML “description” file. I detailed this in this blog post. And we are going to build on that.
So, you are brand new to OfficeJS, and want to get started. The first thing you need to do is get your development environment up and running. There is a script for that:
NOTE: For more information on this script, please read my blog post.
Next, you will need to pull down the Web Add-in Side Loader tool. Keep this ZIP on your desktop. This will be used later in the steps below to make it really easy for you to install the Add-in to Excel. However, if you prefer to do the steps manually, see the link below. For more information on this tool, please see my blog post and/or the GitHub repository.
Now that you have the development environment setup, lets build your very first, super basic Excel add-in:
Create a folder on your desktop called “MyFirstAddIn”
Open Notepad and copy/paste the code from HERE, then click File, Save, name it “manifest.xml”, change the type to “All Files *.*”, browse to folder on your desktop, and click Save.
NOTE: In this step you created the manifest file. This file will be used to “install” the add-in into Excel. Essentially, it will tell Excel where the web page is for the task pane.
Close Notepad, then open it again. Copy paste this code HERE, then click File, Save, name it “home.html”, change the type to “All Files *.*”, browse to the folder on your desktop, and click Save.
NOTE: In this step you created the primary file for website. This one file contains both the HTML and JavaScript needed to make the taskpane load in Excel.
Now you need to side load the manifest and you do that by first opening the ZIP file on your desktop: Set-WebAddin (v1.0.0.0).zip and extracting the Set-WebAddin.exe to the “MyFirstAddIn” folder.
Press Window+R to open the run dialog, and type CMD and press enter.
NOTE: This will open the Windows Command Prompt which you will use to sideload the add-in and run it.
NOTE: The word “sideload” is a fancy way to say install it for only your instance of Excel. It is also known as Developer Sideloading.
Change the directory to the folder on your desktop with this command:
NOTE: In this step you have sideloaded the add-in to Office. This essentially tells Office you have an added an Excel add-in via the information in the manifest file which, when loaded tells Excel everything it needs to know about it, including where to find it. If you prefer to do the sideloading steps manually, you can follow them here.
Now you are almost ready. Type this last command (that is a dot/period at the end, very important):
http-server .
NOTE: The above steps start a local the http-server on your computer so that it will serve the webpage in the browser from the folder (.) you are current inside. You can now test this by clicking this link.
You are now ready to go. Simply open Excel and a new Blank Workbook. Then on the Insert tab, click the down arrow next to My add-ins and click BasicAddin. It should look like this:
The BasicAddIn in the Developer Add-ins menu
Your add-in Task Pane should load.
Click in cell A1, type “Hello World!”, and then in your Task Pane, click the “Click here” button and you should see “Hello World!” in the bottom of the page.
Once you are done, you can press CTRL+C in the command prompt window to shutdown the server and then to uninstall the add-in you can use this command:
And that is it. There are three things to note here:
You created your first web add-in.
You did not use VSCode or any Integrated Development Environment. You did this only with Notepad.
But as an added bonus – you have also installed VSCode and the tools you need to start doing more complex things with Office Web Add-ins.
JavaScript, HTML, Web, CSS, front-end, back-end, web server, ports, local hosts… some, if not all of these are new terms if you are just getting into this new world of the Web and Web add-ins. But it does not have to be that complicated. As I referred to earlier, the following posts should be your next two stops on your journey:
Microsoft has been working hard to make Office available on every platform. One of the biggest changes has been the ability to run Office the a browser or Office online. However, one drawback has been that automation in Office online has been limited to Web Add-ins which are aimed solidly at professional developers. However, Visual Basic for Applications (VBA) macros are only supported in Windows and Mac clients. They are not supported on the web platform, the iOS or Android platforms. And, well, they still are not. However, something new has arrived which will allow you to create “macros” anywhere, on any platform (eventually).
Microsoft recently announced Office Scripts. It is an end-user approachable, web and collaborative supported scripting language. It is still in preview and only supported in Excel online, for now.
First, to access this you must have your administrator enable it in the Office 365 Portal:
For citizen programmers this line from the above page says it all:
Scripts allow you to record and replay your Excel actions on different workbooks and worksheets. If you find yourself doing the same things over and over again, an Office Script can help you by reducing your whole workflow to a single button press.
So, I enabled it in my test tenant and created the quintessential “Hello Wold” Action Recording. When your administrator enables this on your tenant, you will get this new Automation tab:
From there, I clicked on Record Actions, typed “Hello World!” in cell A1, and then stopped the macro. It then asked me to name it and give a description (optional), and then Save. From there it opened the Code Editor and here is what I see:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Let’s say you created the trappings of an add-in with Script Lab and now you want to make it into a stand-alone add-in. You can export your code (just the manifest and html), copy and paste it into an existing project, or upload to GitHub to share it, but you cannot easily convert it into a fully functional Web Add-in project from Script Lab. I took the time to figure this out, so you do not have to. These steps will show you how to export your solution from Script Lab, import into VSCode, apply a Yeoman Office template and then begin testing it in Office Online with, ah… minimal effort (more or less).
Next, we will load one of the sample. On the Script Lab ribbon, click Code.
Click the Samples button and then select Basic API Call.
Next, click the Share button ( )and click Export for publishing, this will download a ZIP file in an Internet Explorer download dialog. Click Open.
If you get a warning open the file, click Allow:
Select these two files, right-click and then click Copy:
basic-api-call.html
basic-api-call-manifest.xml.
Leave the ZIP folder and download window open for now.
Next, create a folder on your computer, call it “sample-1” then Paste (press CTRL+V) the two files into the folder. You can now close the ZIP folder you copied from and the download window.
Open VSCode and press [CTRL+`] to open the Integrated Terminal.
Change to the “sample-1” folder you created above, using the command: cd c:\\sample-1
Type the following command: yo office sample-1
You will then select the option as detailed below:
Once completed, on the File menu, click Open Folder. Browse to the sample-1 folder and click Select location.
Delete the following files and folder:
app.js
app.css
index.html
rousource.html
and the function-file folder
If you want to use Chrome as your debug environment, I would suggest this step which you will click to open the bsconfig.json file and add the following line: “browser”:”chrome” like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Click to open the basic-api-call.html file and remove the following Script Lab lines:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ScriptLab._strings={"unexpectedError":"An unexpected error occurred","authenticationWasCancelledByTheUser":"Authentication was cancelled by the user","officeVersionDoesNotSupportAuthentication":"Your current version of Office does not support displaying an authentication dialog. Please update to a newer version, or try Office Online, if you would like to run this snippet."};
Click to open the basic-api-call-manifest.xml and then CTRL+click to open the sample-1–manifest.xml in a side by side window (on the right).
Copy the following lines from the left pane and replace the same lines by pasting them in the right pane:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Save and close all open files. You can now delete the basic-api-call-manifest.xml file.
Your project is now ready. Press [CTRL+`] to open the Integrated Terminal and type: npm start. Make sure it launches on port 3000 or your add-in will not load:
Your browser will open, if you have a wanting page, click Advanced and then click Proceed to the website. You will not see your index.html.
Open a new tab and browse to https://office365.com and then sign in with your credentials.
From the Office menu, click Excel, then open a new blank workbook.
On the Insert tab, click Office Add-ins.
In the upper right of the dialog, click Upload my add-in. Click Browse and then select the file: c:\<path>\sample-1\sample-1-manifest.xml.
Your adding will now be loaded. On the Home tab, you can click to open the taskpane, click the button and it should highlight the selected cell.
One major caveat is that this is not a preferred way to make a Web Project. This is bare bones and really just to get you going with minimal effort (if you can call ~30 steps minimal effort). The important thing to know is that all your code in going to be embedded in script tags inside the the HTML file and not in a separate JS file (as preferred – a.k.a. Separation of Concerns). So keep that in mind as you perform this work. If eventually your project turns into something much bigger, you will need to do some housekeeping.
So, ~30 steps… It would be nice if there were a way to do this more simply, but for now, this is the best way to do this. I have had a discussion with the product team in charge of Script Lab and they agree with such a feature, so I will update this post if it becomes available at some future point.
I thought I had written this some time ago, but I guess I did not. So here goes…
NOTE: First, I want to state that if you are creating applications for the full Office clients, it might be best to continue using Visual Studio 2017 as you are able to debug directly in these clients with much more ease than you can from VSCode.
Some might find it hard to believe, but I have been geeking out hard and using VSCode to develop OfficeJS (Office 365 Web Add-ins). I find it a very useful, light client, where I am able to focus on just the basics. When combined with tools like Node Package Manager (NPM), browser sync, Yoeman and Git, you have a surprisingly robust development environment what makes doing things delightfully easy. But it was not always this way, I had a learning curve and it took me a while to get it all setup and running correctly. I am not saying it was hard, just… different. So I channeled my inner geek and much to his delight, it turned out for the better.
So as I stated the challenge was getting it all setup. This is going to be very different, especially if you are coming from the Visual Studio 2017 world (much more so, from the VBA world). So, here are the step by step instructions I use for getting my VSCode development environment all configured for Office Development:
Download and install Node to get Node Package Manager (NPM): https://nodejs.org/en/download/. On this page you will want to download the Windows/MSI/64-bit version.
Download and install Git: https://git-scm.com/download. On this page you will want to make sure you select to install the latest which is from the link in the upper right of the page.
Now we have the basic packages we need in order to begin development. What we need to do now is install the Yeoman generator. To do this:
Open VSCode
Press CTRL+`. This will open the console window. Alternatively you can go to the View menu and click Integrated Terminal
Switch to the Terminal in the Console and then type the following command: npm install —global yo
Now you are ready to start generating OfficeJS add-ins from VSCode, and these steps will walk you through the first one:
Type: yo office sample-1
Once you do this the scaffold generator will kick in and ask you a few questions. Answer them as I have, in bold, below:? Would you like to create a new subfolder for your project? No
? Which Office client application would you like to support? Excel
? Would you like to create a new add-in? Yes, I need to create a new web app and manifest file for my add-in.
? Would you like to use TypeScript? No
? Choose a framework: Jquery
? Would you like to open it now while we finish creating your project? Yes
Once complete you will not have a solution folder called sample1 under your user profile c:\users\<yourname>\sample-1, but the project will not be open in VSCode, yet…
To open your project on the File menu, click Open Folder and then browse to and open the sample1 folder, then press Select Folder. NOTE: If you are coming from Visual Studio where the tree of solution files appears on the right side of the screen, the “Explorer” in VSCode appears on the left and it is actually a listing of ALL files and ALL folders in the solution directory.
You will see the code files for your project on the left hand side in the Explorer. The key files of importance to you, getting started will be:
sample-1-manifest.xml – this is your manifest for publishing your add-in.
index.html – this is your primary page or “task pane” for your add-in.
In this example I will not have you edit any of the files, but the basics are completely provided to build a solution. At this point we will check this into Git. Press CTRL+SHIFT+G. This will open the Source Control repository page. Click the icon to the right of the words Source Control, to Initialize Repository. This will open the folder to your solution, simply click Initialize Repository. You can now work with Git to manage your project. I will not go into more detail, but if you are interested, please watch this video: https://git-scm.com/video/what-is-git
Finally, we are ready to debug. But first, if you are on Windows 10, and you use Edge or Internet Explorer as your default browser, I would strongly suggest using the Google Chrome browser because the debug tools are so much better. However, there is one change you need to make:
Open the bsconfig.json file in the Explorer
At the top of the configuration you need to place this line: “browser”: “chrome”, so that the file looks like this:
{
"browser": "chrome",
"ui": {...
To debug, press CTRL+` to open or return to the Integrated Terminal. Type: npm start. This will open your project in Chrome. You might get a warning that the site is not trusted, click Advanced and select to trust anyway / continue.
Open another tab and browse to office365.com. Once there, log into your account. On the Office menu in the upper left, click Excel. On the Insert menu, click Office Add-ins. In the upper right of the dialog, click Upload my add-in. Click Browse and then select the file: c:\users\<yourname>\sample-1\sample-1-manifest.xml. Your add-in will now load on the Home tab, switch there, and press Show Taskpane.
This looks like a lot of work and I know for most of you that are like me, coming from a Visual Studio and/or VBA background, this is very alien. You might consider this a step backwards or it might seem like it is time to hang up the spurs. But give it some time, especially if you are just getting into OfficeJS, it will grow on you. In the meantime, here are some of my other blog entries around this to help you:
Please let me know if you have questions or would like some help with any of this. What I hope to be able to do at some point is to add posts on:
Importing a Script Lab project into a Yo Office scaffold
A video on the steps outlined in this post. I have done videos for internal training at Microsoft before, but never on my own for my blog. So this will be new territory if I can get around to it.
Other samples posts to getting started with various projects.
If you have any ideas of what you would like to see, please let me know.
I have recently updated the OfficeJS.dialogs to version 1.0.8. I have also updated the Node Package Manager version as well. You can get it by running the following command in the VSCode Terminal Window:
npm install officejs.dialogs
With this latest version comes a few bug fixes, some cleanup of the code, cleaner JSDoc documentation and a PrintPreview dialog. The PrintPreview started out as a proof of concept but it actually works for me – in the browser anyway. I am not sure how well it will work in any of the full clients as I have not tested it there yet. If anyone has a chance to test it, please let me know if you encounter any issues.
Here is a sample of the PrintPreview dialog:
Here is some code to implement it:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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