Cyber
Cyber

Reputation: 5000

Export to Excel from javascript not working in IE?

In my asp.Net MVC 4 project i am using a Excel Export functionality which exports an HTML table to Excel file from Client side using Javascript.

Exporting functionality is working fine in Chrome and Firefox but not working in IE(any browser). In IE it just opens a new window and nothings happens.

My javascript code is given below,

function Export(htmltable,filename) {
            var excelFile = "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel' xmlns='http://www.w3.org/TR/REC-html40'>";
            excelFile += "<head>";
            excelFile += "<!--[if gte mso 9]>";
            excelFile += "<xml>";
            excelFile += "<x:ExcelWorkbook>";
            excelFile += "<x:ExcelWorksheets>";
            excelFile += "<x:ExcelWorksheet>";
            excelFile += "<x:Name>";
            excelFile += "{worksheet}";
            excelFile += "</x:Name>";
            excelFile += "<x:WorksheetOptions>";
            excelFile += "<x:DisplayGridlines/>";
            excelFile += "</x:WorksheetOptions>";
            excelFile += "</x:ExcelWorksheet>";
            excelFile += "</x:ExcelWorksheets>";
            excelFile += "</x:ExcelWorkbook>";
            excelFile += "</xml>";
            excelFile += "<![endif]-->";
            excelFile += "</head>";
            excelFile += "<body>";
            excelFile += htmltable.replace(/"/g, '\'');
            excelFile += "</body>";
            excelFile += "</html>";

            var base64data = "base64," + $.base64.encode(excelFile);
            window.open('data:application/vnd.ms-excel;'+ base64data);
 }

I also tried to name the file ,like:

window.open('data:application/vnd.ms-excel;filename=' + filename + ';' + base64data);

but still its naming like 'download.xls'.

How to fix these issues.

I have also found these statements,

If you are targeting Internet Explorer as a browser, you have to look for a different approach, as the current one will not work. From the MSDN library, the data Protocol topic says:

Data URIs are supported only for the following elements and/or attributes.

object (images only)
img
input type=image
link
CSS declarations that accept a URL, such as background, backgroundImage, 
and so on.

Data URIs can be nested.

For security reasons, data URIs are restricted to downloaded resources. Data URIs cannot be used for navigation, for scripting, or to populate frame or iframe elements.

Any approach to overcome this?

Any help is appreciated.

Upvotes: 4

Views: 3441

Answers (1)

fictus
fictus

Reputation: 286

For security reasons newer version if IE no longer support generating files in that form.

My proposed solution (and tested for IE) is to add a new Generic Handler to your MVC project. For this demo I named my ashx handler "Downloader.ashx". Add this code to the generic handler:

    public void ProcessRequest(HttpContext context)
        {
            try
            {
                if (context.Request.QueryString.AllKeys.Contains("fileName"))
                {
                    StreamExcelorWordFile();
                }
            }
            catch (Exception ex)
            {
                HttpContext.Current.Response.Write(ex.Message.ToString());
            }
        }

        public void StreamExcelorWordFile()
        {
            string tableName = HttpContext.Current.Request.QueryString["fileName"].ToString();
            string extensions = HttpContext.Current.Request.QueryString["extension"].ToString();

            //HttpContext.Current.Response.ContentType = "application/force-download";

            string appType = "force-download";
            if (extensions == "xls")
            {
                appType = "vnd.ms-excel";
            }
            else if (extensions == "doc")
            {
                appType = "vnd.ms-word";
            }

            HttpContext.Current.Response.ContentType = "application/" + appType;
            HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + tableName + "." + extensions);

            HttpContext.Current.Response.Write(HttpContext.Current.Request.Form["exportdata"].ToString().Replace("⌐", "<").Replace("¬", ">"));
        }

Then, change your Javascript to something similar to this:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>

<!DOCTYPE html>

<html>
<head runat="server">
    <meta name="viewport" content="width=device-width" />
    <title>Excel or Word Downloader</title>

     <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

    <script type="text/javascript">
        function convertToXLS() {
            var rawHTML = '<table>' + $('#tblTest').html() + '</table>';

            Export(rawHTML, 'myExcelFile', 'xls');
        }

        function Export(htmltable, filename, extension) {
            var JsonHndlrx = "Downloader.ashx";

            htmltable = htmltable.replace(/</g, '⌐').replace(/>/g, '¬');

            $("body").append('<form id="exportform" action="' + JsonHndlrx + '?fileName=' + filename + '&extension=' + extension + '" method="post" target="_blank"><input type="hidden" id="exportdata" name="exportdata" /></form>');
            $("#exportdata").val(htmltable);
            $("#exportform").submit().remove();
            return true;
        }
    </script>
</head>
<body>
    <div>
        <table id="tblTest">
            <tr>
                <th>
                    Column1
                </th>
                <th>
                    Column2
                </th>
                <th>
                    Column3
                </th>
            </tr>
            <tr>
                <td>
                    locationA-1
                </td>
                <td>
                    locationA-2
                </td>
                <td>
                    locationA-3
                </td>
            </tr>
            <tr>
                <td>
                    locationB-1
                </td>
                <td>
                    locationB-2
                </td>
                <td>
                    locationB-3
                </td>
            </tr>
            <tr>
                <td>
                    locationC-1
                </td>
                <td>
                    locationC-2
                </td>
                <td>
                    locationC-3
                </td>
            </tr>
        </table>
    </div>
    <div>
        <input id="btnToExcelDownload" type="button" value="Convert Table To XLS" onclick="convertToXLS(); return false;" />
    </div>
</body>
</html>

Wolla! It should work on all major Browsers including IE!

Upvotes: 1

Related Questions