HTML5 table to CSV file download using frontend JavaScript

OpenJavaScript 0
Reading Time: 3 minutes 🕑

Last updated: July 28, 2022.

In this post, we’ll show you how to go all the way from HTML5 table to a CSV file containing the data in your downloads folder!

Here is the table we’ll be working with:

<table id="my-table">
  <tr>
    <th>Name</th>
    <th>Department</th>
    <th>Contact</th>
  </tr>
  <tr>
    <td>Ted</td>
    <td>IT</td>
    <td>ted@fake-email.com</td>
  </tr>
  <tr>
    <td>Carla</td>
    <td>HR</td>
    <td>carla@fake-email.com</td>
  </tr>
  <tr>
    <td>Brian</td>
    <td>Sales</td>
    <td>brian@fake-email.com</td>
  </tr>
</table>

At the end of the tutorial, we provide you with the code to create a reusable utility function out of the code.

Table of contents

HTML table to CSV

HTML table to data array

To download a HTML5 table as a CSV file, it is first necessary to select the table from the DOM and store its contents in a JavaScript data object.

In the following code, the table is selected. Rows are looped through, with the data cells in each pushed into an array. This array is then push into a final result array (res).

The outcome is an array containing an array of arrays, with each nested array containing the row data as array items.

// Select table rows
const table = document.getElementById('my-table');
const tableRows = table.querySelectorAll('table tr');

// Create a final result array to push data to
const res = [];

// Iterate through the rows
for (let i=0; i<tableRows.length; i++) {

  // Get the current row in loop
  const currentRow = tableRows[i];

  // Create array for current row
  const currentRowArray = [];

  // Iterate through each cell in the row
  for (let j=0; j<currentRow.children.length; j++) {

    // Make the innerHTML an item in the currentRowArray
    currentRowArray.push(currentRow.children[j].innerHTML);

  }

  // Push the complete currentRowArray to the final result array
  res.push(currentRowArray);
  
}

Array to CSV text format

Following this, you can iterate through each item in res (the nested arrays) using map.

You’ll want to use join(",") to merge the items in each nested array separated by a comma. In case the data cells contain commas, you’ll want to use an alternative separator (; or |).

The result of this is an array containing four strings. Now merge these items using join(), but this time by a link break (in a CSV file, a line break represents a new row).

// To CSV format
const mergedRows = res.map(function(row) {
  return row.join(",");
});

const csvData = mergedRows.join("\n");

Creating a file download

Now that the data from the table is in CSV format, it’s time to make it available for download.

You can create a file download using frontend JavaScript by creating a new Blob object (a data container), using URL.createObjectURL() to generate a temporary link and then making this the href attribute of a link element.

// Create the link element
const a = document.createElement('a');

// Store element in a Blob container and specify file type (MIME)
const myBlob = new Blob([csvData], { type: 'text/csv' });

// Generate temporary URL to file and make href of link element
const url = URL.createObjectURL(myBlob);
a.href = url;

// Set file name
a.download = 'table.data.csv';

// Make link element non-visible, append to DOM
a.style.display = "none";
document.body.append(a);

// Simulate click on link element to start download
a.click();

// Remove link element from DOM and delete link (if no longer needed)
a.remove();
URL.revokeObjectURL(url);

Creating a reusable utility function

Below, the HTML5 table to CSV file download functionality is stored in two functions: one for table to CSV text format (tableToCSVData), one for CSV text to file download (downloadCSV).

This allows you to convert any HTML5 you like into a CSV file download in just two lines as many times as you like!

<table id="my-table">
  <tr>
    <th>Name</th>
    <th>Department</th>
    <th>Contact</th>
  </tr>
  <tr>
    <td>Ted</td>
    <td>IT</td>
    <td>ted@fake-email.com</td>
  </tr>
  <tr>
    <td>Carla</td>
    <td>HR</td>
    <td>carla@fake-email.com</td>
  </tr>
  <tr>
    <td>Brian</td>
    <td>Sales</td>
    <td>brian@fake-email.com</td>
  </tr>
</table>

<script>

// With the functions, HTML5 table to CSV file download is now possible in two lines!
const myTable = tableToCSVData('my-table');
downloadCSV(myTable, 'my-table.csv');


function tableToCSVData(inputTable) {

  // Select table rows
  const table = document.getElementById(inputTable);
  const tableRows = table.querySelectorAll('table tr');

  // Create a final result array to push data to
  const res = [];

  // Iterate through the rows
  for (let i=0; i<tableRows.length; i++) {

    // Get the current row in loop
    const currentRow = tableRows[i];

    // Create array for current row
    const currentRowArray = [];

  // Iterate through each cell in the row
  for (let j=0; j<currentRow.children.length; j++) {

    // Make the innerHTML an item in the currentRowArray
    currentRowArray.push(currentRow.children[j].innerHTML);

  }

  // Push the complete currentRowArray to the final result array
  res.push(currentRowArray);
  
}

  // To CSV format
  const mergedRows = res.map(function(row) {
    return row.join(",");
  });

  const csvData = mergedRows.join("\n");

    return csvData;
}

function downloadCSV(data, filename) {

  const a = document.createElement('a');

  const myBlob = new Blob([data], { type: 'text/csv' });

  const url = URL.createObjectURL(myBlob);
  a.href = url;
  a.download = filename;

  a.style.display = "none";
  document.body.append(a);

  a.click();

  a.remove();
  URL.revokeObjectURL(url);

}

</script>

Related links