0

I want to export an HTML table into a spreadsheet that will be created by the JavaScript program. I've considered doing this via the JQuery library but I don't know much about it nor do I think that it will be allowed in my situation. I have seen a solution that uses XML but I don't know much about XML either. What I intend on doing is creating a 2 dimensional array and exporting the contents of that array into Excel. Unfortunately, I don't have control over the tagging scheme and I will have to use getElementsByTagName. The tagging scheme is created via a reporting software.

The below code loops to the second row but it stops at the second row. I can't figure out what I am doing wrong. I hope that somebody will be able to explain a remedy to the error.

<!DOCTYPE html>
<html>
  <body>
    <table>
      <tr><td>a</td><td>1</td></tr>
      <tr><td>b</td><td>2</td></tr>
      <tr><td>c</td><td>3</td></tr>
      <tr><td>d</td><td>4</td></tr>
    </table>

    <script>

      var myNodelist = document.getElementsByTagName("td");
      var NumTD= (document.getElementsByTagName("td").length);
      var NumTR= (document.getElementsByTagName("tr").length);

      var NumCol=NumTD/NumTR;
      var array1 = [[]]; 
      var c=0;
      var r=0;

      alert("NumTD is: "+NumTD);
      for (var i=0;i<=NumTD;i++) {
        alert("On TD: "+i);

        alert(myNodelist[i].innerHTML);

        alert("r: "+r);
        alert("c: "+c); 

        array1[r][c]=myNodelist[i].innerHTML;
        alert("The array is at: "+array1[r][c]);

        if((c+1)==NumCol) {
          c=0;
        } else {
          c++;
        } 

        if(c==0) {
          r++;
        }

      }
    </script>
  </body>
</html>
1
  • your desired end result is a JSON array? how is the table being created? would it not make more sense to convert the raw data from before it was a table and export that? afaik copy and pasting a table from the html page into a spreadsheet manually works. Perhaps a better solution might be to look at adding a 'copy' button like zClip steamdev.com/zclip? Commented Sep 3, 2014 at 3:08

2 Answers 2

2

Issue 1: Work on your formatting. It's a lot easier to debug your own code when you indent correctly, use new lines effectively, and use descriptive variable names.

Issue 2: Uncaught TypeError: Cannot set property '0' of undefined on line 19. You're trying to set array1[0][0] when array1[0] isn't an array. You need to make array[0] an array before you try to use it as one, like this:

if(!array1[i]){
    array1[i] = [];
}

This checks if your array exists. If it doesn't, then it is set to an empty array.

Issue 3: Uncaught TypeError: Cannot read property 'innerHTML' of undefined on line 24. Your loop runs from 0 to 8 and myNodeList only goes up to 7. Changing for (var i=0;i<=NumTD;i++) to for (var i=0;i<NumTD;i++) solves this issue by restricting the bounds of the loop.

Issue 4: Messing around with 3 indices (r, c, and i) is unnecessary and doesn't make things any easier. For one, c and i are always equal, so we can run the loop from c = 0 to c < numTD.

Issue 5: Checking if c + 1 is equal to the number of columns is clumsy. Instead, your second dimension should be c % numCol, which is just the remainder of c divided by numCol. It works perfectly here. We can also increment r when c % numCol is 0.

var myNodelist  =   document.getElementsByTagName("td");
var numTD       =   myNodelist.length;
var numTR       =   document.getElementsByTagName("tr").length;

var numCol  =   numTD/numTR;
var array1  =   [];

var r       =   0;

for(var c = 0; c < numTD; c++){
    array1[r]   =   array1[r] || [];

    array1[r][c % numCol]   =   myNodelist[c].innerHTML;

    if(c % numCol){
        r++;
    }
}

Working example

Issue 6: This approach is generally a clumsy way to accomplish the task. It'd be a lot cleaner to grab each row, iterate through them, and grab the individual cells then. Edit: Got this is right before I saw @dc5's edit. His works just as well.

var rows        =   document.getElementsByTagName("tr");
var results     =   [];

for(var i = 0; i < rows.length; i++){
    var cells   =   rows[i].getElementsByTagName("td");

    results[i]  =   [];

    for(var j = 0; j < cells.length; j++){
        results[i][j]   =   cells[j].innerHTML;
    }
}

Working example

Sign up to request clarification or add additional context in comments.

Comments

1

With your current logic, you have a couple of problems:

  1. array1 is initialized as [[]]
  2. r (the row counter) is never incremented
  3. Your for loop: for (var i=0;i<=NumTD;i++) should be for (var i=0;i<NumTD;i++)

The values read from the table are always updating the value at array1[0,0] and array1[0,1]

The fix - for the current logic, is to increment r when ever the column counter is reset to zero and to insert a new empty array at the new row if it doesn't already exist.

Code:

var myNodelist = document.getElementsByTagName("td");
var NumTD = (document.getElementsByTagName("td").length);
var NumTR = (document.getElementsByTagName("tr").length);

var NumCol = NumTD / NumTR;
var array1 = []; // <== initialize as empty array
var c = 0;
var r = 0;

for (var i = 0; i < NumTD; i++) {
    array1[r] = array1[r] || [];  // <== If array at row doesn't exist, 
                                  //     initialize it to a new array

    array1[r][c] = myNodelist[i].innerHTML;

    if ((c + 1) == NumCol) {
        c = 0;
        r++; // <== increment the row
    } else {
        c++;
    }
}

jsFiddle demo

The above code could be simplified a bit by querying the table rows first, then iterating the rows, querying the child td's for each found row.

For example:

var rows =  document.getElementsByTagName("tr");
var rowCount = rows.length;
var r, c, cols, colCount;

var array1 = [];

for (r = 0; r < rowCount; ++r) {
    array1[r] = [];

    cols = rows[r].getElementsByTagName("td");
    colCount = cols.length;
    for(c = 0; c < colCount; ++c) {
        array1[r][c] = cols[c].innerHTML;
    }
}

jsFiddle demo

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.