Skip to content

Instantly share code, notes, and snippets.

@umidjons
Created March 2, 2015 13:32
Show Gist options
  • Star 60 You must be signed in to star a gist
  • Fork 23 You must be signed in to fork a gist
  • Save umidjons/352da2a4209691d425d4 to your computer and use it in GitHub Desktop.
Save umidjons/352da2a4209691d425d4 to your computer and use it in GitHub Desktop.
Export HTML table to Excel in AngularJS

Export HTML table to Excel in AngularJS

myApp.factory('Excel',function($window){
		var uri='data:application/vnd.ms-excel;base64,',
			template='<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"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>',
			base64=function(s){return $window.btoa(unescape(encodeURIComponent(s)));},
			format=function(s,c){return s.replace(/{(\w+)}/g,function(m,p){return c[p];})};
		return {
			tableToExcel:function(tableId,worksheetName){
				var table=$(tableId),
					ctx={worksheet:worksheetName,table:table.html()},
					href=uri+base64(format(template,ctx));
				return href;
			}
		};
	})
	.controller('MyCtrl',function(Excel,$timeout){
	  $scope.exportToExcel=function(tableId){ // ex: '#my-table'
			$scope.exportHref=Excel.tableToExcel(tableId,'sheet name');
			$timeout(function(){location.href=$scope.fileData.exportHref;},100); // trigger download
		}
	});

How to use:

	<button class="btn btn-link" ng-click="exportToExcel('#table1')">
		<span class="glyphicon glyphicon-share"></span> Export to Excel
	</button>
@emanzuetaj
Copy link

emanzuetaj commented Feb 2, 2018

AngularJS working version with all of the above

    angular
        .module('app')
        .factory('excel', ['$window', '$document', function($window, $document) {
            var uri = 'data:application/vnd.ms-excel;base64,';
            var template =
                '<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"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>';
            var base64 = function(s) { return $window.btoa(unescape(encodeURIComponent(s))); };
            var format = function(s, c) { return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }); };
            return {
                tableToExcel: function(tableId, worksheetName, fileName) {
                    var table = angular.element($document[0].getElementById(tableId));
                    var ctx = { worksheet: worksheetName, table: table.html() };
                    var browser = window.navigator.appVersion;
                    if ((browser.indexOf('Trident') !== -1 && browser.indexOf('rv:11') !== -1) ||
                        (browser.indexOf('MSIE 10') !== -1)) {
                        var builder = new window.MSBlobBuilder();
                        builder.append(uri + format(template, ctx));
                        var blob = builder.getBlob('data:application/vnd.ms-excel');
                        window.navigator.msSaveOrOpenBlob(blob, fileName);
                    } else {
                        var link = $document[0].createElement('a');
                        link.download = fileName;
                        link.href = uri + base64(format(template, ctx));
                        link.click();
                    }
                }
            };
        }]);

Can anyone tell me if there's a way to get rid of the security pop up? It's Microsoft's desired behavior per this post

Anyone able to get custom CSS working for this solution?
Update: answering my own CSS question... CSS must be inline for it to persist

@ankitpachori
Copy link

Dropdowns are also coming in the excel sheet,which is not expected..........

Can anyone guide me on this

@neerajchhatani
Copy link

Dropdowns are also coming in the excel sheet,which is not expected..........

Can anyone guide me on this

@rahiakela
Copy link

rahiakela commented Feb 7, 2018

HI,
Could you give me some reference of html template for Excel that you have used above example. So that I can customise it according to my requirement.

Thanks

@vamsikrishna007
Copy link

Neerajchhatani

Just include only column names and their values. If you are using any dropdown, then take the value of that which is stored in the Scope variable.

@royanon
Copy link

royanon commented Apr 9, 2018

This work in IE, Edge, FF and Chrome. Test on IE11.309.16299.0, Edge 41.16299.248.0, FF 59.2.3, Chrome 65.0.3325.181. Hope this help.
But it doesn't work in chrome when the file exceed 2Mb. It's very easy to hit 2Mb when the html consists of a lot of html.

// factory MyApp.factory('Excel', ["$window", function ($window) { var uri = 'data:application/vnd.ms-excel;base64,', template = '<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"><head><meta meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>', base64 = function (s) { return $window.btoa(unescape(encodeURIComponent(s))); }, format = function (s, c) { return s.replace(/{(\w+)}/g, function (m, p) { return c[p]; }) }; return { tableToExcel: function (tableId, worksheetName, isBase64) { var table = document.querySelector(tableId); var ctx = { worksheet: worksheetName, table: table.innerHTML }; var href = ""; if (isBase64) { href = uri + base64(format(template, ctx)); } else { href = uri + format(template, ctx); } return href; } }; }]); // controller MyApp.controller('MyController', ["$scope", "$timeout", "Excel", function ($scope, $timeout, Excel) { $scope.exportToExcel = function (tableId) { var browser = window.navigator.appVersion; var useBlobBuilder = false; // IE, Edge if ((browser.indexOf('Trident') !== -1 && browser.indexOf('rv:11') !== -1) || (browser.indexOf('MSIE 10') !== -1) || (document.documentMode || /Edge/.test(browser))) { useBlobBuilder = true; $scope.exportHref = Excel.tableToExcel(tableId, 'sheet name', false); } else { //FF, Chrome useBlobBuilder = false; $scope.exportHref = Excel.tableToExcel(tableId, 'sheet name', true); } $timeout(function () { var fileName = "testing.xls"; if (useBlobBuilder) { // IE, Edge var builder = new window.MSBlobBuilder(); builder.append($scope.exportHref); var blob = builder.getBlob('data:application/vnd.ms-excel'); window.navigator.msSaveOrOpenBlob(blob, fileName); } else { //FF, Chrome var link = document.createElement('a'); link.download = fileName; link.href = $scope.exportHref; if (document.body != null) { document.body.appendChild(link); } link.click(); link.remove(); } }, 100); } }]);

@saravanajagan
Copy link

Working fine in Firefox. But not fully working in chrome... if the file size is more its redirecting to blank page.

Any solution?

@paunkumar
Copy link

Working fine.
how to change as filename.

@muadib
Copy link

muadib commented Mar 30, 2019

if the code for download with a custom filename don't work in Firefox, change the else part in tableToExcel with:

var link = document.createElement('a');
link.setAttribute("type", "hidden"); // hide link
link.download = fileName;
link.href = uri + base64(format(template, ctx));
document.body.appendChild(link); //Required for Firefox
link.click();
link.remove();

And add in template, before </head>
<style><!-- table {mso-displayed-decimal-separator: "\.";mso-displayed-thousand-separator: "\,";} --></style>
For specify thousands separator and decimal separator.

@sri15941
Copy link

i am getting only current page data downloaded. but i want all pages data to download.
what can i do.....?

@Noushadkanniyan
Copy link

how to change extenction .xls to xlsx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment