58

I am working on angular js app and I stuck in a situation in which I have to export data to Xls using angular js. I have searched a lot on the internet for export functionality or any library for angular js so I can do that or at least I can get the idea how to export. I don't have any code or work to show here.

I have a data which is an array of objects and I am iterating that on UI in a table. My backend is node.js and frontend are angular js.

My problem is if we have the data from the server and I am using on UI, how can I use the same data to export to Xls using angular js. I don't want to give a call again on the backend to extract the data and export that.

In the existing table, the user can select the checkbox (Any number of rows or all rows) to extract the data to Xls.

In node.js I have used node module whose name is: Excel and it is available on nodemodules site.

My data is like that:

"data": [
    {
        "Name": "ANC101",
        "Date": "10/02/2014",
        "Terms": ["samsung", "nokia": "apple"]
    },{
        "Name": "ABC102",
        "Date": "10/02/2014",
        "Terms": ["motrolla", "nokia": "iPhone"]
    }
]

I want the solution using angularjs or any angularjs library.

starball
  • 20,030
  • 7
  • 43
  • 238
w3uiguru
  • 5,864
  • 2
  • 21
  • 25
  • What is the actual question? From what I am reading you know how to do the export, correct? If you know how to do the export what is it you need to know from an AngularJS perspective to get your task done? – gonzofish Feb 10 '14 at 15:31
  • @gonzofish, thanks to show your interest in this question. I m updating my ques. – w3uiguru Feb 10 '14 at 15:41
  • 1
    I believe the only way to do this is to do a call back to the server. JavaScript (on the front-end at least) doesn't have the capabilities to do that sort of thing. – gonzofish Feb 10 '14 at 15:49

9 Answers9

65

A cheap way to do this is to use Angular to generate a <table> and use FileSaver.js to output the table as an .xls file for the user to download. Excel will be able to open the HTML table as a spreadsheet.

<div id="exportable">
    <table width="100%">
        <thead>
            <tr>
                <th>Name</th>
                <th>Email</th>
                <th>DoB</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="item in items">
                <td>{{item.name}}</td>
                <td>{{item.email}}</td>
                <td>{{item.dob | date:'MM/dd/yy'}}</td>
            </tr>
        </tbody>
    </table>
</div>

Export call:

var blob = new Blob([document.getElementById('exportable').innerHTML], {
        type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"
    });
    saveAs(blob, "Report.xls");
};

Demo: http://jsfiddle.net/TheSharpieOne/XNVj3/1/

Updated demo with checkbox functionality and question's data. Demo: http://jsfiddle.net/TheSharpieOne/XNVj3/3/

Jelle den Burger
  • 1,428
  • 17
  • 31
TheSharpieOne
  • 25,646
  • 9
  • 66
  • 78
  • 11
    With Office 2013 you will get the warning: "The file format and extension dont match... The file could be corrupted...". Any idea how to solve this? – fischermatte Apr 20 '14 at 10:20
  • I have LibreOffice installed and normally have no problems opening excel files, but I can open the files generated by your code. – user1354603 Aug 19 '14 at 15:00
  • Would it be possible to style the cell; text color, background color, regular/bold/italic? – lvarayut Jan 06 '15 at 14:45
  • Yes, use inline styles (the `style` attribute) on the `` and it will be shown in excel. You can also use ``/``/`` tags. See http://jsfiddle.net/TheSharpieOne/XNVj3/303/ – TheSharpieOne Jan 07 '15 at 14:51
  • @fischermatte I have a same problem did you solved it? If yes, could you provide me with answer. Thanks in advance – Erlan Feb 20 '15 at 17:25
  • The JSFiddles work for me as-is from Chrome 42 and Firefox 38, opening in OpenOffice Calc 4.1, which I state only as information for others. @Erlan: Suggestion for the Office 2013 issue (which is more of a wild, stab-in-the-dark guess, since I don't use MS Office): try renaming the file "something.xlsx". I would be interested to know if that helps. – Grant Lindsay May 15 '15 at 01:40
  • @Grant Lindsay: Than Excel refuses to open the file making het even worse... This is a very weird solution because the file just contains the html and not an xsl format. This is why you get a message that the file format and the extension don't match. – Roel Jul 22 '15 at 12:45
  • 2
    @fischermatte: You can't fix that within this solution because that is exactly what you do. Let Excel open a html file with the wrong extension. Excel is nice enough to show it in a table but it is not a clean solution. – Roel Jul 27 '15 at 09:04
  • Yeah, a noted in the answer, this is a cheap solution. No need for large library to create a proprietary format, but the downside is that warning that pops up. – TheSharpieOne Jul 27 '15 at 12:37
  • Is it possible to set options like word wrap etc too? The issue I am facing is that that the data is exceeding the column width. Thus, while printing the excel, the data gets truncated. And the thing is that I am not taking the data from the HTML page. I am creating custom data in the JS file and then sending it to excel. Thus, the style tags in my HTML page cannot be used here. Thanks in advance. – Mitaksh Gupta Aug 10 '15 at 07:15
  • 2
    this is not proper solution , if we add style to table without using inline , then it does not works. – Amay Kulkarni Oct 05 '15 at 17:11
  • It is not a solution: it is a weird hack to fool Windows to open a html file with Excel. Then excel tries to make something out of it. This is not hackoverflow so I don't understand all the upvotes. – Roel Jun 14 '16 at 09:00
  • 1
    Impossible to use the file after generation. Perhaps the file type declared need to be changed. – Mateus Leon Jul 05 '16 at 18:09
  • This solution is not proper along with pagination if i have large number of records because the table displayed will be having data as per the pagination but report generated should have all the records instead of records which are only visible on the screen in the table – Pushpendra Pal Dec 30 '16 at 07:26
  • @PushpendraPal this works with pagination. Your display table will have e pagination, but your export table doesn't (it just renders everything). If the problem is that your data is not all on the clientnto export, then no [purely] client side solution will work for you. – TheSharpieOne Dec 30 '16 at 14:21
  • 1
    why do we need .xls, why not just .csv?? – Alexander Mills Mar 09 '17 at 23:12
  • You can use the same gross solution with CSV, rename to XLS and excel will open it. – Charlie Apr 18 '17 at 07:45
  • 1
    It's not possible to style a csv document the same way or at all as far as I know. – TheSharpieOne Apr 18 '17 at 13:18
  • hi all iam also doing same functionality i need to increase the column width of excel help – jose Jun 12 '17 at 13:14
  • is it possible to convert to xlsx instead xls? – Julyano Felipe Jul 04 '17 at 17:03
  • @JulyanoFelipe you should be able to just change `xls` to `xlsx` in the `saveAs` call. – TheSharpieOne Jul 05 '17 at 15:52
  • @TheSharpieOne ok, it is saving as extension "xlsx" but, when trying to open file, it's showing a error: "Excel cannot open the file 'filename.xlsx' because the file format for the file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file." in Excel 2016 – Julyano Felipe Jul 05 '17 at 19:13
  • 1
    I am getting error like saveAs is not defined in controller.js – Sachin HR Oct 09 '17 at 07:48
  • 1
    The demo doesn't work anymore, I found the fix: downgrade the version of the file server: npm install file-server@1.3.3 --save . Because the version 1.3.4 doesn't support FileSaver.saveAs – Rafael Paredes Mar 21 '18 at 17:09
24

You can try Alasql JavaScript library which can work together with XLSX.js library for easy export of Angular.js data. This is an example of controller with exportData() function:

function myCtrl($scope) {
  $scope.exportData = function () {
    alasql('SELECT * INTO XLSX("john.xlsx",{headers:true}) FROM ?',[$scope.items]);
  };

  $scope.items = [{
    name: "John Smith",
    email: "j.smith@example.com",
    dob: "1985-10-10"
  }, {
    name: "Jane Smith",
    email: "jane.smith@example.com",
    dob: "1988-12-22"
  }];
}

See full HTML and JavaScript code for this example in jsFiddle.

UPDATED Another example with coloring cells.

Also you need to include two libraries:

agershun
  • 4,077
  • 38
  • 41
  • how can i give some css to header?? like bold and colored header and one blank colored line just below header?? – amitkumar12788 Feb 23 '15 at 05:25
  • the example in jsFiddler produces an empty .xlsx file. is this something you can fix? please test before publishing. – user2378769 Mar 28 '15 at 00:03
  • @amitkumar12788 Now AlaSQL supports CSS style properties in cells. Please, see the example: http://jsfiddle.net/agershun/95j0txwx/2/ – agershun Apr 18 '15 at 06:31
  • @agershun thanks for reply, It's really good. I think all css is not reflecting here. I am working on ubuntu and i have libre office in which only header is in bold and other css is not working. is there any solution for this?? will this work on microsoft office 2013 or above?? – amitkumar12788 Apr 19 '15 at 08:05
  • Yes, the current method (export with HTML) works only for MS, but incompatible with LibreOffice. We will continue to work on this. – agershun Apr 19 '15 at 14:06
  • 1
    Thanks for the incredibly helpful post why do i need to include the XLsx.core.min.js it seems to work without it? @agershun – Frank Visaggio Jun 08 '16 at 18:24
  • Unfortunatly this does not generate an excel file. It just generates a html file with a xls extension just like TheSharpieOne answer. – Roel Jun 14 '16 at 09:04
  • But it can generate real xlsx files!: http://jsfiddle.net/gd7jex9s/. It uses this lib internaly: https://github.com/SheetJS/js-xlsx – Roel Jun 14 '16 at 09:12
  • getting this error "The file format and extension dont match... The file could be corrupted" Any idea how to resolve this? – SAN Jul 12 '17 at 11:30
16

When I needed something alike, ng-csv and other solutions here didn't completely help. My data was in $scope and there were no tables showing it. So, I built a directive to export given data to Excel using Sheet.js (xslsx.js) and FileSaver.js.

Here is my solution packed.

For example, the data is:

$scope.jsonToExport = [
    {
      "col1data": "1",
      "col2data": "Fight Club",
      "col3data": "Brad Pitt"
    },
    {
      "col1data": "2",
      "col2data": "Matrix Series",
      "col3data": "Keanu Reeves"
    },
    {
      "col1data": "3",
      "col2data": "V for Vendetta",
      "col3data": "Hugo Weaving"
    }
];

I had to prepare data as array of arrays for my directive in my controller:

$scope.exportData = [];
// Headers:
$scope.exportData.push(["#", "Movie", "Actor"]);
// Data:
angular.forEach($scope.jsonToExport, function(value, key) {
  $scope.exportData.push([value.col1data, value.col2data, value.col3data]);
});

Finally, add directive to my template. It shows a button. (See the fiddle).

<div excel-export export-data="exportData" file-name="{{fileName}}"></div>
Kursad Gulseven
  • 1,978
  • 1
  • 24
  • 26
12

If you load your data into ng-grid, you can use the CSV export plugin. The plugin creates a button with the grid data as csv inside an href tag.

http://angular-ui.github.io/ng-grid/

https://github.com/angular-ui/ng-grid/blob/2.x/plugins/ng-grid-csv-export.js

Updating links as the library got renamed:

Github link: https://github.com/angular-ui/ui-grid

Library page: http://ui-grid.info/

Documentation on csv export : http://ui-grid.info/docs/#/tutorial/206_exporting_data

Bala Sivagnanam
  • 863
  • 1
  • 15
  • 30
debovis
  • 123
  • 1
  • 6
9

One starting point could be to use this directive (ng-csv) just download the file as csv and that's something excel can understand

http://ngmodules.org/modules/ng-csv

Maybe you can adapt this code (updated link):

http://jsfiddle.net/Sourabh_/5ups6z84/2/

Altough it seems XMLSS (it warns you before opening the file, if you choose to open the file it will open correctly)

var tableToExcel = (function() {

  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 function(table, name) {
    if (!table.nodeType) table = document.getElementById(table)
    var ctx = {worksheet: name || 'Worksheet', table: table.innerHTML}
    window.location.href = uri + base64(format(template, ctx))
  }
})()
Braulio
  • 1,748
  • 14
  • 23
4

Try below with customised file name:

$scope.exportData= function(){                  
    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]; }) }

          var table = document.getElementById("searchResult");
          var filters = $('.ng-table-filters').remove();
          var ctx = {worksheet: name || 'Worksheet', table: table.innerHTML};
          $('.ng-table-sort-header').after(filters) ;          
          var url = uri + base64(format(template, ctx));
          var a = document.createElement('a');
          a.href = url;
          a.download = 'Exported_Table.xls';
          a.click();        
};
Matt
  • 3,079
  • 4
  • 30
  • 36
0
$scope.ExportExcel= function () { //function define in html tag                          

                        //export to excel file
                        var tab_text = '<table border="1px" style="font-size:20px" ">';
                        var textRange;
                        var j = 0;
                        var tab = document.getElementById('TableExcel'); // id of table
                        var lines = tab.rows.length;

                        // the first headline of the table
                        if (lines > 0) {
                            tab_text = tab_text + '<tr bgcolor="#DFDFDF">' + tab.rows[0].innerHTML + '</tr>';
                        }

                        // table data lines, loop starting from 1
                        for (j = 1 ; j < lines; j++) {
                            tab_text = tab_text + "<tr>" + tab.rows[j].innerHTML + "</tr>";                                
                        }

                        tab_text = tab_text + "</table>";
                        tab_text = tab_text.replace(/<A[^>]*>|<\/A>/g, "");          //remove if u want links in your table
                        tab_text = tab_text.replace(/<img[^>]*>/gi, "");             // remove if u want images in your table
                        tab_text = tab_text.replace(/<input[^>]*>|<\/input>/gi, ""); // reomves input params

                        // console.log(tab_text); // aktivate so see the result (press F12 in browser)               
                        var fileName = 'report.xls'                            
                        var exceldata = new Blob([tab_text], { type: "application/vnd.ms-excel;charset=utf-8" }) 

                        if (window.navigator.msSaveBlob) { // IE 10+
                            window.navigator.msSaveOrOpenBlob(exceldata, fileName);
                            //$scope.DataNullEventDetails = true;
                        } else {
                            var link = document.createElement('a'); //create link download file
                            link.href = window.URL.createObjectURL(exceldata); // set url for link download
                            link.setAttribute('download', fileName); //set attribute for link created
                            document.body.appendChild(link);
                            link.click();
                            document.body.removeChild(link);
                        }

                    }

        //html of button 

Mr.Ngo
  • 51
  • 3
0

I had this problem and I made a tool to export an HTML table to CSV file. The problem I had with FileSaver.js is that this tool grabs the table with html format, this is why some people can't open the file in excel or google. All you have to do is export the js file and then call the function. This is the github url https://github.com/snake404/tableToCSV if someone has the same problem.

snake_404
  • 111
  • 5
  • 15
0

We need a JSON file which we need to export in the controller of angularjs and we should be able to call from the HTML file. We will look at both. But before we start, we need to first add two files in our angular library. Those two files are json-export-excel.js and filesaver.js. Moreover, we need to include the dependency in the angular module. So the first two steps can be summarised as follows -

  1. Add json-export.js and filesaver.js in your angular library.

  2. Include the dependency of ngJsonExportExcel in your angular module.

       var myapp = angular.module('myapp', ['ngJsonExportExcel'])
    

Now that we have included the necessary files we can move on to the changes which need to be made in the HTML file and the controller. We assume that a json is being created on the controller either manually or by making a call to the backend.

HTML :

Current Page as Excel
All Pages as Excel 

In the application I worked, I brought paginated results from the backend. Therefore, I had two options for exporting to excel. One for the current page and one for all data. Once the user selects an option, a call goes to the controller which prepares a json (list). Each object in the list forms a row in the excel.

Read more at - https://www.oodlestechnologies.com/blogs/Export-to-excel-using-AngularJS

Disclaimer: I work for oodles technologies

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219