19

My table is in format

<table id="mytable">
<thead>
  <tr>
    <th>name</th>
    <th>place</th>
  </tr>
</thead>
<tbody>
<tr>
   <td>adfas</td>
   <td>asdfasf</td>
</tr>
</tbody>
</table>

I found the following code online. But it doesn't work if i use "thead" and "tbody" tags

function write_to_excel() {

    str = "";

    var mytable = document.getElementsByTagName("table")[0];
    var rowCount = mytable.rows.length;
    var colCount = mytable.getElementsByTagName("tr")[0].getElementsByTagName("td").length;

    var ExcelApp = new ActiveXObject("Excel.Application");
    var ExcelSheet = new ActiveXObject("Excel.Sheet");
    ExcelSheet.Application.Visible = true;

    for (var i = 0; i < rowCount; i++) {
        for (var j = 0; j < colCount; j++) {
            str = mytable.getElementsByTagName("tr")[i].getElementsByTagName("td")[j].innerHTML;
            ExcelSheet.ActiveSheet.Cells(i + 1, j + 1).Value = str;
        }
    }
Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
user755043
  • 1,657
  • 3
  • 12
  • 12
  • 2
    Javascript is browser side language, you can convert an HTML document to PDF using a server side language. Also note that ActiveXObject solution are not portable, it only works on IE. – Emre Yazici Jul 04 '11 at 02:34
  • The solution there won't work without IE – Pablo Fernandez Jul 04 '11 at 02:35
  • 1
    Non-IE solution here: http://stackoverflow.com/questions/6955627/export-dynamic-html-table-to-excel-in-javascript-in-firefox-browser –  Oct 03 '12 at 19:22

13 Answers13

13

Check https://github.com/linways/table-to-excel. Its a wrapper for exceljs/exceljs to export html tables to xlsx.

TableToExcel.convert(document.getElementById("simpleTable1"));
<script src="https://cdn.jsdelivr.net/gh/linways/table-to-excel@v1.0.4/dist/tableToExcel.js"></script>
<table id="simpleTable1" data-cols-width="70,15,10">
<tbody>
    <tr>
        <td class="header" colspan="5" data-f-sz="25" data-f-color="FFFFAA00" data-a-h="center" data-a-v="middle" data-f-underline="true">
            Sample Excel
        </td>
    </tr>
    <tr>
        <td colspan="5" data-f-italic="true" data-a-h="center" data-f-name="Arial" data-a-v="top">
            Italic and horizontal center in Arial
        </td>
    </tr>
    <tr>
        <th data-a-text-rotation="90">Col 1 (number)</th>
        <th data-a-text-rotation="vertical">Col 2</th>
        <th data-a-wrap="true">Wrapped Text</th>
        <th data-a-text-rotation="-45">Col 4 (date)</th>
        <th data-a-text-rotation="-90">Col 5</th>
    </tr>
    <tr>
        <td rowspan="1" data-t="n">1</td>
        <td rowspan="1" data-b-b-s="thick" data-b-l-s="thick" data-b-r-s="thick">
            ABC1
        </td>
        <td rowspan="1" data-f-strike="true">Striked Text</td>
        <td data-t="d">05-20-2018</td>
        <td data-t="n" data-num-fmt="$ 0.00">2210.00</td>
    </tr>

    <tr>
        <td rowspan="2" data-t="n">2</td>
        <td rowspan="2" data-fill-color="FFFF0000" data-f-color="FFFFFFFF">
            ABC 2
        </td>
        <td rowspan="2" data-a-indent="3">Merged cell</td>
        <td data-t="d">05-21-2018</td>
        <td data-t="n" data-b-a-s="dashed" data-num-fmt="$ 0.00">230.00</td>
    </tr>
    <tr>
        <td data-t="d">05-22-2018</td>

        <td data-t="n" data-num-fmt="$ 0.00">2493.00</td>
    </tr>

    <tr>
        <td colspan="4" align="right" data-f-bold="true" data-a-h="right" data-hyperlink="https://google.com">
            <b><a href="https://google.com">Hyperlink</a></b>
        </td>
        <td colspan="1" align="right" data-t="n" data-f-bold="true" data-num-fmt="$ 0.00">
            <b>4933.00</b>
        </td>
    </tr>
    <tr>
        <td colspan="4" align="right" data-f-bold="true" data-a-rtl="true">
            مرحبا
        </td>
        <td colspan="1" align="right" data-t="n" data-f-bold="true" data-num-fmt="$ 0.00">
            <b>2009.00</b>
        </td>
    </tr>
    <tr>
        <td data-b-a-s="dashed" data-b-a-c="FFFF0000">All borders</td>
    </tr>
    <tr>
        <td data-t="b">true</td>
        <td data-t="b">false</td>
        <td data-t="b">1</td>
        <td data-t="b">0</td>
        <td data-error="#VALUE!">Value Error</td>
    </tr>
    <tr>
        <td data-b-t-s="thick" data-b-l-s="thick" data-b-b-s="thick" data-b-r-s="thick" data-b-t-c="FF00FF00" data-b-l-c="FF00FF00" data-b-b-c="FF00FF00" data-b-r-c="FF00FF00">
            All borders separately
        </td>
    </tr>
    <tr data-exclude="true">
        <td>Excluded row</td>
        <td>Something</td>
    </tr>
    <tr>
        <td>Included Cell</td>
        <td data-exclude="true">Excluded Cell</td>
        <td>Included Cell</td>
    </tr>
</tbody>
</table>

This creates valid xlsx on the client side. Also supports some basic styling. Check https://codepen.io/rohithb/pen/YdjVbb for a working example.

Rohith
  • 1,301
  • 3
  • 21
  • 31
  • This code is no longer working, either update or delete the answer. – Atul Kumar May 13 '19 at 05:00
  • 1
    @AtulKumar I have re-written everything on version 1.x. Now the usage is changed a little bit, since I changed the underlying library to exceljs. You can find a working example at: https://codepen.io/rohithb/pen/YdjVbb. – Rohith May 14 '19 at 05:10
10

Only works in Mozilla, Chrome and Safari..

$(function() {
  $('button').click(function() {
    var url = 'data:application/vnd.ms-excel,' + encodeURIComponent($('#tableWrap').html())
    location.href = url
    return false
  })
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>

</script>
<button>click me</button>
<div id="tableWrap">
  <table>
    <thead>
      <tr>
        <th>A</th>
        <th>B</th>
        <th>C</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
    </tbody>
  </table>
</div>
Sphinx
  • 10,519
  • 2
  • 27
  • 45
Tabares
  • 4,083
  • 5
  • 40
  • 47
8

The reason the solution you found on the internet is no working is because of the line that starts var colCount. The variable mytable only has two elements being <thead> and <tbody>. The var colCount line is looking for all the elements within mytable that are <tr>. The best thing you can do is give an id to your <thead> and <tbody> and then grab all the values based on that. Say you had <thead id='headers'> :

function write_headers_to_excel() 
{
  str="";

  var myTableHead = document.getElementById('headers');
  var rowCount = myTableHead.rows.length;
  var colCount = myTableHead.getElementsByTagName("tr")[0].getElementsByTagName("th").length; 

var ExcelApp = new ActiveXObject("Excel.Application");
var ExcelSheet = new ActiveXObject("Excel.Sheet");
ExcelSheet.Application.Visible = true;

for(var i=0; i<rowCount; i++) 
{   
    for(var j=0; j<colCount; j++) 
    {           
        str= myTableHead.getElementsByTagName("tr")[i].getElementsByTagName("th")[j].innerHTML;
        ExcelSheet.ActiveSheet.Cells(i+1,j+1).Value = str;
    }
}

}

and then do the same thing for the <tbody> tag.

EDIT: I would also highly recommend using jQuery. It would shorten this up to:

function write_to_excel() 
{
 var ExcelApp = new ActiveXObject("Excel.Application");
 var ExcelSheet = new ActiveXObject("Excel.Sheet");
 ExcelSheet.Application.Visible = true; 

  $('th, td').each(function(i){
    ExcelSheet.ActiveSheet.Cells(i+1,i+1).Value = this.innerHTML;
  });
}

Now, of course, this is going to give you some formatting issues but you can work out how you want it formatted in Excel.

EDIT: To answer your question about how to do this for n number of tables, the jQuery will do this already. To do it in raw Javascript, grab all the tables and then alter the function to be able to pass in the table as a parameter. For instance:

var tables = document.getElementsByTagName('table');
for(var i = 0; i < tables.length; i++)
{
  write_headers_to_excel(tables[i]);
  write_bodies_to_excel(tables[i]);
}

Then change the function write_headers_to_excel() to function write_headers_to_excel(table). Then change var myTableHead = document.getElementById('headers'); to var myTableHead = table.getElementsByTagName('thead')[0];. Same with your write_bodies_to_excel() or however you want to set that up.

Charles Caldwell
  • 16,649
  • 4
  • 40
  • 47
  • Thank you very much. It worked . I have one more question. How do i use the function if there are n tables in my html page. – user755043 Jul 04 '11 at 04:35
  • 3
    All though it is a shame that this only works in IE, the OP was not about how to make his code work across multiple browsers. It was about why his current code wasn't working with the table he had. Delving into the issue of making a javascript work in multiple browsers (which is the purpose of JS to begin with) I felt was outside the scope of this question. Personally, I never use IE unless forced to by my company's intranet. – Charles Caldwell Aug 23 '12 at 14:40
  • @prashu132 'Tis very true that this only works in IE. (And a shame as my previous comment mentioned.) If you are looking for a more cross browser solution, I would suggest pushing the data to the server side and doing the generation there before pushing it back to the client. It also appears there is a solution using a jQuery plugin located in [this SO question](http://stackoverflow.com/questions/5524143/how-can-i-export-tables-to-excel-from-a-webpage) – Charles Caldwell Jun 10 '13 at 03:34
  • @CharlesCaldwell : i found another answer which might be a better one. Please try it out and vote it up if good and useful. Thank you. – Prashanth Shyamprasad Jun 10 '13 at 03:57
  • You never use this var ExcelApp = new ActiveXObject("Excel.Application"); in both javascript or jquery . I could not get this to work in IE 10 either – Tom Stickel Oct 22 '15 at 20:24
  • @TomStickel Thanks for pointing this out. It is true that `ExcelApp` is never used in the code. I copied that line from the OP's code so I can only assume the OP uses it at some point. As far as IE 10, I have not tested this code in quite some time. I'll make a note to boot up my Windows machine and give it a try. – Charles Caldwell Oct 22 '15 at 22:25
  • I ended up using this solution http://stackoverflow.com/questions/22317951/export-html-table-data-to-excel-using-javascript-jquery-is-not-working-properl It is working great in both Chrome and IE ( the selected answer) – Tom Stickel Oct 23 '15 at 01:24
6

This might be a better answer copied from this question.

<script type="text/javascript">
function generate_excel(tableid) {
  var table= document.getElementById(tableid);
  var html = table.outerHTML;
  window.open('data:application/vnd.ms-excel;base64,' + base64_encode(html));
}

function base64_encode (data) {
  // http://kevin.vanzonneveld.net
  // +   original by: Tyler Akins (http://rumkin.com)
  // +   improved by: Bayron Guevara
  // +   improved by: Thunder.m
  // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // +   bugfixed by: Pellentesque Malesuada
  // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // +   improved by: Rafal Kukawski (http://kukawski.pl)
  // *     example 1: base64_encode('Kevin van Zonneveld');
  // *     returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
  // mozilla has this native
  // - but breaks in 2.0.0.12!
  //if (typeof this.window['btoa'] == 'function') {
  //    return btoa(data);
  //}
  var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
    ac = 0,
    enc = "",
    tmp_arr = [];

  if (!data) {
    return data;
  }

  do { // pack three octets into four hexets
    o1 = data.charCodeAt(i++);
    o2 = data.charCodeAt(i++);
    o3 = data.charCodeAt(i++);

    bits = o1 << 16 | o2 << 8 | o3;

    h1 = bits >> 18 & 0x3f;
    h2 = bits >> 12 & 0x3f;
    h3 = bits >> 6 & 0x3f;
    h4 = bits & 0x3f;

    // use hexets to index into b64, and append result to encoded string
    tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
  } while (i < data.length);

  enc = tmp_arr.join('');

  var r = data.length % 3;

  return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);

}
</script>
Ryan M
  • 18,333
  • 31
  • 67
  • 74
Prashanth Shyamprasad
  • 827
  • 2
  • 17
  • 39
6
Excel Export Script works on IE7+ , Firefox and Chrome
===========================================================



function fnExcelReport()
    {
             var tab_text="<table border='2px'><tr bgcolor='#87AFC6'>";
             var textRange; var j=0;
          tab = document.getElementById('headerTable'); // id of table


          for(j = 0 ; j < tab.rows.length ; j++) 
          {     
                tab_text=tab_text+tab.rows[j].innerHTML+"</tr>";
                //tab_text=tab_text+"</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

               var ua = window.navigator.userAgent;
              var msie = ua.indexOf("MSIE "); 

                 if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./))      // If Internet Explorer
                    {
                           txtArea1.document.open("txt/html","replace");
                           txtArea1.document.write(tab_text);
                           txtArea1.document.close();
                           txtArea1.focus(); 
                            sa=txtArea1.document.execCommand("SaveAs",true,"Say Thanks to Sumit.xls");
                          }  
                  else                 //other browser not tested on IE 11
                      sa = window.open('data:application/vnd.ms-excel,' + encodeURIComponent(tab_text));  


                      return (sa);
                            }

    Just Create a blank iframe
    enter code here
        <iframe id="txtArea1" style="display:none"></iframe>

    Call this function on

        <button id="btnExport" onclick="fnExcelReport();"> EXPORT 
        </button>
sampopes
  • 2,646
  • 1
  • 22
  • 34
  • 1
    Newer version of this script is almost ready with extra features. Will be publishing it soon. – sampopes Jun 03 '15 at 13:14
  • @sampopes Thanks for your useful solution. I have a question based on your answer and I would like to seek your advice please. I have a table, the pagesize is 10 because I have to show 10 rows/records for each page. The table contains 18 rows/records, so the table will have 2 pages, in the button if I click the button to export to excel, it can show row/records in page 1. However in page 2, if I click the button to export excel, it shows rows/records in page 1. – Learner Oct 10 '17 at 01:40
  • @sampopes (cont) At this moment, I guess maybe the browser (Internet Explorer) remembers the content in page 1, so I refresh the browser, click the page 2 of the table and click the button to export the excel, howerver it (the excel) still shows rows/records in page 1. What I have tried: I add another iframe `txtArea2` and add code for `txtArea2` inside the function. I run the program, the result is the same. Do you have idea about how to export table data based on table pages? Thank you very much. – Learner Oct 10 '17 at 01:40
3
    function XLExport() {
        try {
            var i;
            var j;
            var mycell;
            var tableID = "tblInnerHTML";

            var objXL = new ActiveXObject("Excel.Application");
            var objWB = objXL.Workbooks.Add();
            var objWS = objWB.ActiveSheet;

            for (i = 0; i < document.getElementById('<%= tblAuditReport.ClientID %>').rows.length; i++) {
                for (j = 0; j < document.getElementById('<%= tblAuditReport.ClientID %>').rows(i).cells.length; j++) {
                    mycell = document.getElementById('<%= tblAuditReport.ClientID %>').rows(i).cells(j);
                    objWS.Cells(i + 1, j + 1).Value = mycell.innerText;
                }
            }

            //objWS.Range("A1", "L1").Font.Bold = true;

            objWS.Range("A1", "Z1").EntireColumn.AutoFit();

            //objWS.Range("C1", "C1").ColumnWidth = 50;

            objXL.Visible = true;

        }
        catch (err) {
                    }

    }
1

Check this out... I just got this working and it seems exactly what you are trying to do as well.

2 functions. One to select the table and copy it to the clipboard, and the second writes it to excel en masse. Just call write_to_excel() and put in your table id (or modify it to take it as an argument).

  function selectElementContents(el) {
        var body = document.body, range, sel;
        if (document.createRange && window.getSelection) {
            range = document.createRange();
            sel = window.getSelection();
            sel.removeAllRanges();
            try {
                range.selectNodeContents(el);
                sel.addRange(range);
            } catch (e) {
                range.selectNode(el);
                sel.addRange(range);
            }
        } else if (body.createTextRange) {
            range = body.createTextRange();
            range.moveToElementText(el);
            range.select();
        }
        range.execCommand("Copy");
    }

function write_to_excel() 
{
var tableID = "AllItems";
selectElementContents( document.getElementById(tableID) );

var excel = new ActiveXObject("Excel.Application");
// excel.Application.Visible = true; 
var wb=excel.WorkBooks.Add();
var ws=wb.Sheets("Sheet1");
ws.Cells(1,1).Select;
ws.Paste;
ws.DrawingObjects.Delete;
ws.Range("A1").Select
 excel.Application.Visible = true; 
}

Heavily influenced from: Select a complete table with Javascript (to be copied to clipboard)

Community
  • 1
  • 1
dah97765
  • 679
  • 1
  • 13
  • 29
0

I think you can also think of alternative architectures. Sometimes something can be done in another way much more easier. If the producer of HTML file is you, then you can write an HTTP handler to create an Excel document on the server (which is much more easier than in JavaScript) and send a file to the client. If you receive that HTML file from somewhere (like an HTML version of a report), then you still can use a server side language like C# or PHP to create the Excel file still very easily. I mean, you may have other ways too. :)

Saeed Neamati
  • 35,341
  • 41
  • 136
  • 188
0

I try this with jquery; use this and have fun :D

    jQuery.printInExcel = function (DivID) 
{ 
var ExcelApp = new ActiveXObject("Excel.Application"); 
ExcelApp.Workbooks.Add; 
ExcelApp.visible = true; 
var str = ""; 
var tblcount = 0; 
var trcount = 0;
 $("#" + DivID + " table").each(function () 
{ $(this).find("tr").each(function () 
{ var tdcount = 0; $(this).find("td").each(function () 
{ str = str + $(this).text(); ExcelApp.Cells(trcount + 1, tdcount + 1).Value = str; 
str = ""; tdcount++ 
}); 
trcount++ 
}); tblcount++ 
}); 
};

use this in your class and call it with $.printInExcel(your var);

Trikaldarshiii
  • 11,174
  • 16
  • 67
  • 95
0

I would suggest using a different approach. Add a button on the webpage that will copy the content of the table to the clipboard, with TAB chars between columns and newlines between rows. This way the "paste" function in Excel should work correctly and your web application will also work with many browsers and on many operating systems (linux, mac, mobile) and users will be able to use the data also with other spreadsheets or word processing programs.

The only tricky part is to copy to the clipboard because many browsers are security obsessed on this. A solution is to prepare the data already selected in a textarea, and show it to the user in a modal dialog box where you tell the user to copy the text (some will need to type Ctrl-C, others Command-c, others will use a "long touch" or a popup menu).

It would be nicer to have a standard copy-to-clipboard function that possibly requests a user confirmation... but this is not the case, unfortunately.

6502
  • 112,025
  • 15
  • 165
  • 265
0

function exportExcelFromTable(){

let table = document.getElementById('tableId');
console.log(table); 

TableToExcel.convert(table, { 
    name: `export.xlsx`,
    sheet: {
      name: 'Exported_Data' // sheetName
    }
  });

}

0
exportTable() {
if (this.arrayname.length >= 1) { //here your array name which are display in table
    $('#exportable tr td').css('text-align', 'center'); //table formating
    const downloadLink = document.createElement('a');
    const table = document.getElementById('exportable');
    const tableHTML = table.outerHTML.replace(/ /g, '%20');
    var html = table.outerHTML;
    var url = 'data:application/vnd.ms-excel,' + escape(html); // Set your html table into url 
    downloadLink.href = 'data:' + url + ' ';
    downloadLink.download = 'tablename.xls'
    downloadLink.click();
} else {
    alert('table is empty')
}}
`        //table tab should be like this     <table class="table class" id="exportable" border="1" style="border-collapse: collapse;">
//button   <button class="btn btn-xs btn-primary "(click)="exportTable();">
                     <i class="fa fa-file-excel-o m-right-5"></i>
                     <span>Export Excel</span>
                     </button>    
  • This is fully working code ,plz try it and vote – Rajkumar Dhariya Feb 03 '22 at 07:12
  • Can you [edit] your post to more explain why this should answer the question ? Also, it seems very different from the original code. Finally, this is an old question with already accepted answer, so not sure your one will be... – Elikill58 Feb 03 '22 at 08:32
0

HTML

<table class="table-box">
            <tbody>
                <tr>
                    <td>Americano</td>
                    <td>$ 3.00</td>
                </tr>
                <tr>
                    <td>Cappuccino</td>
                    <td>$ 3.00</td>
                </tr>
                <tr>
                    <td>Double Espresso</td>
                    <td>$ 3.50</td>
                </tr>
                <tr>
                    <td>Latte</td>
                    <td>$ 4.20</td>
                </tr>
                <tr>
                    <td>Macchiato</td>
                    <td>$ 4.50</td>
                </tr>
                <tr>
                    <td>Mint Chocolate</td>
                    <td>$ 5.25</td>
                </tr>
                <tr>
                    <td>Mocha</td>
                    <td>$ 4.50</td>
                </tr>
                <tr>
                    <td>White Mocha</td>
                    <td>$ 5.00</td>
                </tr>
            </tbody>
        </table>

Javascript:

 function exportTableToExcel(filename = '') {
    var downloadLink;
    var dataType = 'application/vnd.ms-excel';
    var tableSelect = document.querySelectorAll(".table-box");
    var tableHTML;
    for (let i = 0; i < tableSelect.length; i++) {
        tableHTML += tableSelect[i].outerHTML.replace(/ /g, '%20');
    }
    // Specify file name
    filename = filename ? filename + '.xls' : 'excel_data.xls';

    // Create download link element
    downloadLink = document.createElement("a");

    document.body.appendChild(downloadLink);

    if (navigator.msSaveOrOpenBlob) {
        var blob = new Blob(['\ufeff', tableHTML], {
            type: dataType
        });
        navigator.msSaveOrOpenBlob(blob, filename);
    } else {
        // Create a link to the file
        downloadLink.href = 'data:' + dataType + ', ' + tableHTML;

        // Setting the file name
        downloadLink.download = filename;

        //triggering the function
        downloadLink.click();
    }
}

HTML to call the javascript function:

   <div class="export-xls">
    <button onclick="exportTableToExcel('exported-menu')">Export Menu as Excel File</button>
   </div>