Search This Blog

Wednesday, March 16, 2016

Excel export directly from Javascript

Modern HTML pages relies more and more on JavaScript (or other languages which compiles to it). Personally I use Typescript but at the end of the day it's basically the same, as the code run is run by the JavaScript engine, and it's the browser which must deal with it.

I saw that some of my users had a need to copy results from one of the many lists my software produce and paste it inside Excel. I thought "wouldn't be cool if there was a button to do that automatically?"

Sure I could produce a CSV (coma separated values) file in a text area which would then allows to easily paste inside anything else. However I wanted something a bit more sophisticated. Why? Because what if I want to have some formatting for example and also reduce the number of manual steps.

So the first step for me was to investigate about file format Excel today uses. I worked long time ago with the old Excel 2.0 binary format (which is somewhat easy to produce), and the previous version of my software was using Excel directly via COM+ (interop). I know that latest office products works with XML and thought, well I could produce the XML directly, shouldn't be soooo hard. My bad! The standard Excel format is indeed XML.... but multiple files scattered inside a directory structure and then Zipped. Not something you really want to do in JavaScript.

After checking a bit more I discovered a "pure" XML format which could be produced. This format is actually pretty straight forward:

https://en.wikipedia.org/wiki/Microsoft_Office_XML_formats#Excel_XML_Spreadsheet_example

Actually this can be further simplified by removing some of the tags which are not mandatory.

Anyhow, starting using this one, I could produce an XML out of my result list, remains the question of how to send it back to the user. Again sure I could write it down on a text area and let the user copy / paste it, but that's somewhat not what I wanted.

So how to send back the data to the user? Well there is actually 2 roads:

For Chrome:
var link = <any>document.createElement('a');
link.download = "my.xlm";
link.href = "data:application/vnd.ms-excel;filename=my.xlm;base64," + btoa(excel);
link.click();

For Firefox:
document.location.href = "data:application/vnd.ms-excel;base64," + btoa(excel);

Why two roads? Yes Chrome could handle the thing the same way as Firefox but you cannot really handle the file name with it (or I didn't succeed at it).

What's going on here? Basically you create a pseudo location or a link to a pseudo location which contains data, as the mime type (application/vnd.ms-excel) triggers the download the data will be downloaded. The data must be base64 encoded and that's what btoa does.

I didn't succeed to make it work with IE but at least 2 of the major browser work.

No comments:

Post a Comment