3

I have some JavaScript code as given under first code snippet, that works in latest Chrome but not in latest FireFox. This code is exporting data to xls file using Blob object. The strange thing is that in FireFox, the code does not throw any error but does nothing as it executes all the lines successfully i.e. no export happens.

A demo for this question is at this URL: http://js.do/sun21170/84920

If you run the code in above demo in Chrome, it will download the file newfile.xls ( allow popups in Chrome).

Question: What change I need to make in Blob Code given below, in order to make it work in FireFox? I tried using type: 'application/octet-stream' and also type: 'text/plain', but both did not help in FireFox.

The variable table in code snippet below holds a string that is the html for rendering a table including html and body tags.

Blob Code for exporting (not working in FireFox)

 //export data in Chrome or FireFox
 //this works in Chrome but not in FireFox
 //also no errors in firefox
 sa = true;
 var myBlob =  new Blob( [table] , {type:'text/html'});
 var url = window.URL.createObjectURL(myBlob);
 var a = document.createElement("a");
 document.body.appendChild(a);
 a.href = url;
 a.download = "newfile.xls";
 a.click();
 window.URL.revokeObjectURL(url);
Sunil
  • 20,653
  • 28
  • 112
  • 197

3 Answers3

8

The answer to my question is as explained below.

The problem was that the line window.URL.revokeObjectURL(url) was being called too soon for FireFox to react to a.click() and show it's file dialog. So, I just added a delay by using setTimeout for the line window.URL.revokeObjectURL(url). This change made it work in FireFox. Of course, it worked in Chrome also.

The updated code is as below which has only one change in the last line of code. Also, the demo with this change that works in FireFox is: http://js.do/sun21170/84977

Blob Code for exporting (this works in FireFox and Chrome)

 //export data in Chrome or FireFox
 //this works in Chrome as well as in FireFox
 sa = true;
 var myBlob =  new Blob( [table] , {type:'text/html'});
 var url = window.URL.createObjectURL(myBlob);
 var a = document.createElement("a");
 document.body.appendChild(a);
 a.href = url;
 a.download = "newfile.xls";
 a.click();
//adding some delay in removing the dynamically created link solved the problem in FireFox
 setTimeout(function() {window.URL.revokeObjectURL(url);},0);

While the above code works perfectly, I think when exporting to xls file, it's better to use type:'application/vnd.ms-excel even though the table variable holds a html string.

This small change makes FireFox automatically use Excel as the default program for opening the exported file else FireFox uses Laucnch Windows app (default) to open the file. This default app on my laptop was Edge browser.

var myBlob =  new Blob( [table] , {type:'application/vnd.ms-excel'});

If you would like to use 100% client-side approach in older IE browsers, then Blob object cannot be used since it's not available in older IE browsers, but you can use another approach as in code snippet below.

Exporting Html to Excel in IE <= IE 11 including IE 8 and IE 9

function ExportTabletoExcelInOldIE(table) 
{
 //table variable contains the html to be exported to Excel
 var sa = null;
 var ua = window.navigator.userAgent;
 var msie = ua.indexOf("MSIE ");
 if (msie > 0)  // If old Internet Explorer including IE 8
    {
        //make sure you have an empty div with id of iframeDiv in your page
        document.getElementById('iframeDiv').innerHTML = '<iframe id="txtArea1" style="display:none"></iframe>';
        txtArea1.document.open("txt/html", "replace");
        txtArea1.document.write(table);
        txtArea1.document.close();
        txtArea1.focus();
        sa = txtArea1.document.execCommand("SaveAs", true, "DataExport.xls");
        document.getElementById('iframeDiv').innerHTML = "";
    }
 return (sa);
}

For above IE specific code to work, add following to your page markup.

Empty Div needed when exporting in older IE browsers

<div id='iframeDiv'></div>
Sunil
  • 20,653
  • 28
  • 112
  • 197
  • Thanks Sunil, Using this method we are able to save the Excel right away, can you please tell, what should be done to give alert message for user to (open/save/saveAs) using these options. your help is much appreciated. – Disera Apr 12 '16 at 09:31
  • @Disera, The `Save File` dialog is browser dependent. Older IE browsers should automatically popup this dialog. You don't need to write any code to show this dialog. – Sunil Apr 12 '16 at 15:44
  • I use IE9 and i dont get this popup for (open/save/saveAs), i directly get the `save` dialog box. Can you please tell if i am going wrong anywhere? – Disera Apr 13 '16 at 05:43
  • And also, Can you please tell, is there any way to avoid a specific column `` from being exported to excel, say by using it's id? – Disera Apr 13 '16 at 07:14
  • What other dialog besides the `save` dialog you want? That is the only dialog that is shown by browsers. – Sunil Apr 13 '16 at 14:19
  • If you want to avoid a `td` element from being exported, then you have to make sure that the parameter `table` that is passed to function `ExportTabletoExcelInOldIE` excludes that `td` element. The parameter `table` can be customized by you in any manner so you include and exclude rows and columns according to your requirements. – Sunil Apr 13 '16 at 14:22
  • Thanks a lot Sunil ! Won't the browser asks for suggestion like ( view/ save) when we open a pdf or excel file? In this case, i get only the `save` option not the viewing. Thats what i meant in the comment. – Disera Apr 15 '16 at 12:48
  • The browser will only show a Save dialog. I have never seen a View dialog in any of the major browsers. – Sunil Apr 15 '16 at 16:27
  • Sunil, what i meant was, when you click on "export" button, the browser shows a dialog box like -> Example : https://jsfiddle.net/lesson8/jWAJ7/ (in fiddle example : when the export button is clicked, the browser shows a dialog box with options `open with` and `save file`). what should be done to get a dialog box like the above? Can you please give an idea? – Disera Apr 19 '16 at 13:30
  • 1
    @Disera, This dialog shows up in IE browser as well as other browsers. If your code is correct this dialog is automatically shown by the browser. If you are not seeing this dialog, then post your code and mention in which browser the dialog doesn't show. It has to be a mistake/bug in your code if you are not seeing this dialog. – Sunil Apr 19 '16 at 15:29
  • Sunil, I have posted the question here : http://stackoverflow.com/questions/36720402/html-export-to-excel-browser-directly-saves-the-excel-cannot-open-in-view-m Can you please help? – Disera Apr 20 '16 at 06:18
1

You can try to add the anchor to the dom like this:

document.body.appendChild(a);
a.click();
document.body.removeChild(a);
Wenjia
  • 11
  • 1
0

I know this trouble with Blob and CSV Export. My solution: Create an Array and POST it to a backend script. Then you can simply create a Excel, CSV, PDF etc.

Citrullin
  • 2,269
  • 14
  • 29
  • I was looking for a client-side only solution in my case. Your approach will work but it would not be a 100% client-side approach. – Sunil Feb 28 '16 at 18:55
  • What happen in Firefox? – Citrullin Feb 28 '16 at 19:05
  • No error. It just goes through the blob code and does nothing. I just found the problem and posted the solution under `UPDATE 1`. – Sunil Feb 28 '16 at 19:07
  • Is there a way to export excel (html table) without using `Blob`, since it's not supported in IE9 and lower versions. Please suggest an idea!Thanks. – Disera Apr 07 '16 at 08:12
  • Yep. Javascript Array -> HTTP POST to Backend Service -> Serialization -> to Excel – Citrullin Apr 08 '16 at 09:47
  • @Disera, Look at my answer on how to export using 100% client-side approach in older IE browsers like IE 8 and IE 9 in which `Blob` object is not supported. Just make sure to add the necessary markup as mentioned in answer for this to work in older IE browsers. – Sunil Apr 09 '16 at 16:03
  • Sunil i tried your approach, it works fine.Thanks!! But i have many inner tables inside my main table. Using this method, it treats anything within a as a row. So everything inside a comes into a single cell. how to recognize the inner and write it's in the 2nd row of the excel sheet. Can you please help?
    – Disera Apr 11 '16 at 09:53
  • @Philipp Blum ,Can you please show a sample snippet of how to create an Array and Post it to Backend script? It will be helpful for many. Thanks in Advance! – Disera Apr 11 '16 at 09:56