Thursday, May 30, 2019

Export data as CSV File with javascript in salesforce Lightning Web Component(lwc)

This post explains how to export data table data as a CSV file using javascript in salesforce Lightning web component(lwc).

I created a simple Lighting web component, this component is displayed Account data and one button to download CSV file.

Example:
exportDataToCSVInLWC.html
<template>
    <lightning-card title="Export Data as CSV in Lightning Web Components" icon-name="custom:custom63">
        <template if:true={data}>
            <div class="slds-p-around_medium lgc-bg-inverse">
                <p>Do you want download data as a CSV format, Click Here &nbsp;
                    <lightning-button icon-name="utility:download" 
                                      label="Download as CSV" 
                                      title="Download CSV File"
                                      onclick={downloadCSVFile} variant="brand"></lightning-button>
                </p>
            </div>
            <div class="slds-m-around_medium">
                <!-- Datatable component -->
                    <lightning-datatable columns={columns} 
                                         data={data} 
                                         hide-checkbox-column="true"
                                         key-field="id"></lightning-datatable>
            
            </div>
        </template>
    </lightning-card>
</template>

exportDataToCSVInLWC.js
import { LightningElement, track} from 'lwc';
// importing accounts
import getAccountList from '@salesforce/apex/LWCExampleController.getAccounts';
// imported to show toast messages
import {ShowToastEvent} from 'lightning/platformShowToastEvent';


// datatable columns
const cols = [
    {label: 'Name',fieldName: 'Name'}, 
    {label: 'Industry',fieldName: 'Industry'},
    {label: 'Type',fieldName: 'Type'}, 
    {label: 'Phone',fieldName: 'Phone',type: 'phone'}, 
    {label: 'Rating',fieldName: 'Rating'}, 
    {label: 'Account Number',fieldName: 'AccountNumber'}, 
];

export default class ExportDataToCSVInLWC extends LightningElement {
    @track error;
    @track data;
    @track columns = cols;

    // this constructor invoke when component is created.
    // once component is created it will fetch the accounts
    constructor() {
        super();
        this.getallaccounts();
    }

    // fetching accounts from server
    getallaccounts() {
        getAccountList()
        .then(result => {
            this.data = result;
            this.error = undefined;
        })
        .catch(error => {
            this.error = error;
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Error while getting Accounts', 
                    message: error.message, 
                    variant: 'error'
                }),
            );
            this.data = undefined;
        });
    }

    // this method validates the data and creates the csv file to download
    downloadCSVFile() {   
        let rowEnd = '\n';
        let csvString = '';
        // this set elminates the duplicates if have any duplicate keys
        let rowData = new Set();

        // getting keys from data
        this.data.forEach(function (record) {
            Object.keys(record).forEach(function (key) {
                rowData.add(key);
            });
        });

        // Array.from() method returns an Array object from any object with a length property or an iterable object.
        rowData = Array.from(rowData);
        
        // splitting using ','
        csvString += rowData.join(',');
        csvString += rowEnd;

        // main for loop to get the data based on key value
        for(let i=0; i < this.data.length; i++){
            let colValue = 0;

            // validating keys in data
            for(let key in rowData) {
                if(rowData.hasOwnProperty(key)) {
                    // Key value 
                    // Ex: Id, Name
                    let rowKey = rowData[key];
                    // add , after every value except the first.
                    if(colValue > 0){
                        csvString += ',';
                    }
                    // If the column is undefined, it as blank in the CSV file.
                    let value = this.data[i][rowKey] === undefined ? '' : this.data[i][rowKey];
                    csvString += '"'+ value +'"';
                    colValue++;
                }
            }
            csvString += rowEnd;
        }

        // Creating anchor element to download
        let downloadElement = document.createElement('a');

        // This  encodeURI encodes special characters, except: , / ? : @ & = + $ # (Use encodeURIComponent() to encode these characters).
        downloadElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csvString);
        downloadElement.target = '_self';
        // CSV File Name
        downloadElement.download = 'Account Data.csv';
        // below statement is required if you are using firefox browser
        document.body.appendChild(downloadElement);
        // click() Javascript function to download CSV file
        downloadElement.click(); 
    }

}

exportDataToCSVInLWC.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="exportDataToCSVInLWC">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Apex Class
public inherited sharing class LWCExampleController {
    
    @AuraEnabled(Cacheable = true)
    public static List<Account> getAccounts(){
      return [SELECT Id, Name,Industry, Type, Phone, Rating, AccountNumber FROM Account ORDER BY Name LIMIT 10];
    }
}

Result:

7 comments:

  1. how to remove id field in csv file

    ReplyDelete
  2. How can I change the row header and the column order?

    ReplyDelete
  3. Is there a way to customize those fields? For example the length or the color of a specific field.

    ReplyDelete
  4. What is size limit for the CSV file and how many records does the download supports?

    ReplyDelete
  5. not downloading the csv if am in lightning version. downloading file with "download" as name not as .csv extension. but this works in Classic version. any help?

    ReplyDelete
  6. Thank you for your post it has been very educational! I am using a lightning:tree-grid and would like to apply this logic to include an export to csv link. Unfortunately, I am fairly new to Salesforce and am not sure how to break out the child row object(s). Can you suggest what I might do to modify your solution for a tree-grid? Thank you for your time and assistance!

    ReplyDelete