ANGULAR 5 : how to export data to csv file

My solution currently is making a service for the saving (I got this from Changhui Xu @ codeburst). No package installs needed for this...

import { Injectable } from '@angular/core';

declare global {
    interface Navigator {
        msSaveBlob?: (blob: any, defaultName?: string) => boolean
    }
}

@Injectable({
    providedIn: 'root',
})
export class CsvDataService {
    exportToCsv(filename: string, rows: object[]) {
      if (!rows || !rows.length) {
        return;
      }
      const separator = ',';
      const keys = Object.keys(rows[0]);
      const csvContent =
        keys.join(separator) +
        '\n' +
        rows.map(row => {
          return keys.map(k => {
            let cell = row[k] === null || row[k] === undefined ? '' : row[k];
            cell = cell instanceof Date
              ? cell.toLocaleString()
              : cell.toString().replace(/"/g, '""');
            if (cell.search(/("|,|\n)/g) >= 0) {
              cell = `"${cell}"`;
            }
            return cell;
          }).join(separator);
        }).join('\n');
  
      const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
      if (navigator.msSaveBlob) { // IE 10+
        navigator.msSaveBlob(blob, filename);
      } else {
        const link = document.createElement('a');
        if (link.download !== undefined) {
          // Browsers that support HTML5 download attribute
          const url = URL.createObjectURL(blob);
          link.setAttribute('href', url);
          link.setAttribute('download', filename);
          link.style.visibility = 'hidden';
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);
        }
      }
    }
  }

And then I inject this service in my component. It then calls this service:


  constructor(private csvService :CsvDataService) {}

  saveAsCSV() {
    if(this.reportLines.filteredData.length > 0){
      const items: CsvData[] = [];

      this.reportLines.filteredData.forEach(line => {
        let reportDate = new Date(report.date);
        let csvLine: CsvData = {
          date: `${reportDate.getDate()}/${reportDate.getMonth()+1}/${reportDate.getFullYear()}`,
          laborerName: line.laborerName,
          machineNumber: line.machineNumber,
          machineName: line.machineName,
          workingHours: line.hours,
          description: line.description
        }
        items.push(csvLine); 
      });

      this.csvService.exportToCsv('myCsvDocumentName.csv', items);
    }
    
  }

Update: Here is slightly better way to do it:

  1. Open up command prompt in the directory of your project.
  2. Install file-saver by typing npm install --save file-saver
  3. import { saveAs } from 'file-saver'; into your .ts file.
  4. Here is the updated code based on the new import.
downloadFile(data: any) {
    const replacer = (key, value) => value === null ? '' : value; // specify how you want to handle null values here
    const header = Object.keys(data[0]);
    let csv = data.map(row => header.map(fieldName => JSON.stringify(row[fieldName], replacer)).join(','));
    csv.unshift(header.join(','));
    let csvArray = csv.join('\r\n');

    var blob = new Blob([csvArray], {type: 'text/csv' })
    saveAs(blob, "myFile.csv");
}

Credits to this answer for converting an object to CSV.

Here is the method to use:

downloadFile(data: any) {
  const replacer = (key, value) => (value === null ? '' : value); // specify how you want to handle null values here
  const header = Object.keys(data[0]);
  const csv = data.map((row) =>
    header
      .map((fieldName) => JSON.stringify(row[fieldName], replacer))
      .join(',')
  );
  csv.unshift(header.join(','));
  const csvArray = csv.join('\r\n');

  const a = document.createElement('a');
  const blob = new Blob([csvArray], { type: 'text/csv' });
  const url = window.URL.createObjectURL(blob);

  a.href = url;
  a.download = 'myFile.csv';
  a.click();
  window.URL.revokeObjectURL(url);
  a.remove();
}

I'll add on later if I found a better way to do it.