Daniel
Daniel

Reputation: 673

Giving each row a variable when converting an HTML table to CSV

So I'm writing a simple web app that all it does is load a CSV, add an "agree?" checkbox to the end of each row, then downloads the table as CSV.

That downloaded CSV will later be converted to an SQL table, but before that, I need to find a way to give each row a boolean variable based on what the user checked or didn't check.

So here's the JS which is built out of a few functions that load a CSV, add the checkbox I mentioned, then convert it back.

function buildHeaderElement (header) {
    const headerEl = document.createElement('thead')
    headerEl.append(buildRowElement(header, true))
    return headerEl
  }

  function buildRowElement (row, header) {
    const columns = row.split(',')
    const rowEl = document.createElement('tr')

    for (column of columns) {
      const columnEl = document.createElement(`${header ? 'th' : 'td'}`)
      columnEl.textContent = column
      rowEl.append(columnEl)
    }            

    rowEl.append(provideeColumnAgree(row, header))
    return rowEl
  }

    function provideeColumnAgree(row, header) {
        const columnAgree = document.createElement(`${header ? 'th' : 'td'}`)
    
    if(header)
    {
        columnAgree.textContent = 'Agree?';
    }
    else
    {    
        const checkboxAgree = document.createElement(`input`) 
      checkboxAgree.setAttribute("type", "checkbox");
        columnAgree.append(checkboxAgree)
    }
    
    return columnAgree    
    }

  function populateTable (tableEl, rows) {
    const rowEls = [buildHeaderElement(rows.shift())]

    for (const row of rows) {
      if (!row) { continue }
      rowEls.push(buildRowElement(row))
    }

    tableEl.innerHTML= ''
    return tableEl.append(...rowEls)
  }

  function createSubmitBtn() {
  var button = document.createElement("button");
  button.innerHTML = "Download CSV";
  var body = document.getElementsByTagName("body")[0];
  body.appendChild(button);
  button.addEventListener ("click", function() {
    exportTableToCSV('members.csv')
  });
  }

  function downloadCSV(csv, filename) {
    var csvFile;
    var downloadLink;

    // CSV file
    csvFile = new Blob([csv], {type: "text/csv"});
    downloadLink = document.createElement("a");
    downloadLink.download = filename;
    downloadLink.href = window.URL.createObjectURL(csvFile);
    downloadLink.style.display = "none";
    downloadLink.click();
}

  function exportTableToCSV(filename) {
    var csv = [];
    var rows = document.querySelectorAll("table tr");
    
    for (var i = 0; i < rows.length; i++) {
        var row = [], cols = rows[i].querySelectorAll("td, th");
        
        for (var j = 0; j < cols.length; j++) 
            row.push(cols[j].innerText);
        
        csv.push(row.join(","));        
    }

    // Download CSV file
    downloadCSV(csv.join("\n"), filename);
}


  function readSingleFile ({ target: { files } }) {
    const file = files[0]
    const fileReader = new FileReader()
    const status = document.getElementById('status')

    if (!file) {
      status.textContent = 'No file selected.'
      return
    }

    fileReader.onload = function ({ target: { result: contents } }) {

        status.textContent = `File loaded: ${file.name}`
        const tableEl = document.getElementById('csvOutput')
        const lines = contents.split('\n')

        populateTable(tableEl, lines)
        status.textContent = `Table built from: ${file.name}`
        createSubmitBtn()
    }
    fileReader.readAsText(file)
  }

  window.addEventListener('DOMContentLoaded', _ => {
    document.getElementById('fileSelect').addEventListener('change', readSingleFile)
  })

The HTML is quite simple

<html>
<body>
  <input type="file" id="fileSelect"/>
  <div id="status">Waiting for CSV file.</div>
  <table id="csvOutput"></table>
  <script src="script.js"></script>
</body>
</html>

Here's the link to the project: https://jsfiddle.net/95tjsom3/1/

Upvotes: 0

Views: 290

Answers (1)

T.Shah
T.Shah

Reputation: 2768

While downloading the csv, you can check whether the column contains checkbox or not. And if it has a checkbox, whether it is checked or not. Then you can alter the contents of that particular column.

function exportTableToCSV(filename) {
    var checkboxes = document.getElementsByTagName("input");  // get all checkboxes in the array
    var csv = [];
    var rows = document.querySelectorAll("table tr");

    for (var i = 0; i < rows.length; i++) {
        var row = [], cols = rows[i].querySelectorAll("td, th");

        for (var j = 0; j < cols.length; j++) { 
            if(cols[j].innerHTML.includes('<input type="checkbox">')) {
               if(checkboxes[i].checked) {
                   row.push("AGREE");
               }
               else {
                   row.push("NOT AGREE");
               } 
            }
            else {
                row.push(cols[j].innerText);
            }
        }

        csv.push(row.join(","));        
    }

    // Download CSV file
    downloadCSV(csv.join("\n"), filename);
}

Upvotes: 1

Related Questions