csv fle download in lightning component

Download Data as CSV File With JavaScript In Salesforce Lightning Component

Lightning Component

Hi guys, Today In this post we are seeing that how to Download/Export Data as CSV File format With Client Side JavaScript controller In Salesforce Lightning Component.

What is the CSV File ?  

CSV stands for “comma-separated values”. CSV is a simple file format used to store tabular data, like a spreadsheet or database. Its data fields are most often separated,  by a comma. Files in the CSV format can be imported to and exported from programs that store data in tables, such as Microsoft Excel or OpenOffice etc.

Prerequisites : basic understanding of Lightning Component, JavaScript and Apex Programming.

In This Sample, we will create a simple Lightning Component which is showing the Contact [salesforce standard object] Records. and also creating a HTML Button to download table data as CSV format.

Output:

CSV File download from lightning component

CSV File:

CSV File download from lightning component

apex Controller [csvDownloadCtrl.apxc]
public class csvDownloadCtrl {
@AuraEnabled
   public static list <contact> fetchContact(){
      
      List <contact> returnConList = new List < contact > ();
        
      for(contact con: [SELECT firstName, LastName, Department, MobilePhone From contact LIMIT 1000]) {
             returnConList.add(con);
          }
         return returnConList;
   }
}
  • Above apex class is just return the List of Contact Records.
Lightning Component [csvSample.cmp]
<aura:component controller="csvDownloadCtrl">          
    <!--aura init handler , call js "loadContactList" function on component load, and display contact data on table-->   
    <aura:handler name="init" value="{!this}" action="{!c.loadContactList}"/> 
    
    <!--Declare Attribute for store Contact Records List-->  
    <aura:attribute name="ListOfContact" type="contact[]"/> 
    
 <!--Use "slds-m-around- -xx-large" class to add standard Large padding to the component--> 
  <div class="slds-m-around--xx-large">   
    <button class="slds-button slds-button--brand" onclick="{!c.downloadCsv}">Download As CSV</button> <br/><br/>

<!--HTML tabel for display Contact Records-->
<table class="slds-table slds-table--bordered slds-table--cell-buffer">
  <thead>
    <tr class="slds-text-title--caps">
       
        <th class="slds-is-sortable slds-text-title--caps" scope="col">
          <span class="slds-truncate" title="Name">First Name</span>  
       </th>
        
       <th class="slds-is-sortable slds-text-title--caps" scope="col">
          <span class="slds-truncate" title="Last Name">Last Name</span>
       </th>
        
      <th class="slds-is-sortable slds-text-title--caps" scope="col">
          <span class="slds-truncate" title="Department">Department</span>
       </th>
        
      <th scope="col">
        <div class="slds-truncate" title="MobilePhone">Mobile Phone</div>
      </th>
    </tr>
  </thead>
    <!--table body start, 
      Iterate contact list as a <tr>
     -->
  <tbody>
    <aura:iteration items="{!v.ListOfContact}" var="con">  
    <tr>
      <th scope="row">
        <div class="slds-truncate" title="{!con.FirstName}">{!con.FirstName}</div>
      </th>
        
      <th scope="row">
        <div class="slds-truncate" title="{!con.LastName}">{!con.LastName}</div>
      </th>
        
       <th scope="row">
        <div class="slds-truncate" title="{!con.Department}">{!con.Department}</div>
      </th>
        
       <th scope="row">
        <div class="slds-truncate" title="{!con.MobilePhone}">{!con.MobilePhone}</div>
      </th> 
    </tr>
       
    </aura:iteration>
    
  </tbody>
</table> 
    </div>
</aura:component>
  • See Code Comments
JavaScript Controller [csvSampleController.js]
({
    // ## function call on component load  
    loadContactList: function(component, event, helper){
       helper.onLoad(component, event);
    },
    
    // ## function call on Click on the "Download As CSV" Button. 
    downloadCsv : function(component,event,helper){
        
        // get the Records [contact] list from 'ListOfContact' attribute 
        var stockData = component.get("v.ListOfContact");
        
        // call the helper function which "return" the CSV data as a String   
        var csv = helper.convertArrayOfObjectsToCSV(component,stockData);   
         if (csv == null){return;} 
        
        // ####--code for create a temp. <a> html tag [link tag] for download the CSV file--####     
	     var hiddenElement = document.createElement('a');
          hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csv);
          hiddenElement.target = '_self'; // 
          hiddenElement.download = 'ExportData.csv';  // CSV file Name* you can change it.[only name not .csv] 
          document.body.appendChild(hiddenElement); // Required for FireFox browser
    	  hiddenElement.click(); // using click() js function to download csv file
        }, 
 })
  • See Code Comments
JavaScript Helper [csvSampleHelper.js]
({
   onLoad: function(component, event) {
      //call apex class method
      var action = component.get('c.fetchContact');
      action.setCallback(this, function(response){
         //store state of response
         var state = response.getState();
         if (state === "SUCCESS") {
            //set response value in ListOfContact attribute on component.
            component.set('v.ListOfContact', response.getReturnValue());
         }
      });
      $A.enqueueAction(action);
   },
    
   convertArrayOfObjectsToCSV : function(component,objectRecords){
        // declare variables
        var csvStringResult, counter, keys, columnDivider, lineDivider;
       
        // check if "objectRecords" parameter is null, then return from function
        if (objectRecords == null || !objectRecords.length) {
            return null;
         }
        // store ,[comma] in columnDivider variabel for sparate CSV values and 
        // for start next line use '\n' [new line] in lineDivider varaible  
        columnDivider = ',';
        lineDivider =  '\n';

        // in the keys valirable store fields API Names as a key 
        // this labels use in CSV file header  
        keys = ['FirstName','LastName','Department','MobilePhone','Id' ];
        
        csvStringResult = '';
        csvStringResult += keys.join(columnDivider);
        csvStringResult += lineDivider;

        for(var i=0; i < objectRecords.length; i++){   
            counter = 0;
           
             for(var sTempkey in keys) {
                var skey = keys[sTempkey] ;  

              // add , [comma] after every String value,. [except first]
                  if(counter > 0){ 
                      csvStringResult += columnDivider; 
                   }   
               
               csvStringResult += '"'+ objectRecords[i][skey]+'"'; 
               
               counter++;

            } // inner for loop close 
             csvStringResult += lineDivider;
          }// outer main for loop close 
       
       // return the CSV formate String 
        return csvStringResult;        
    },
})
  • See Code Comments
  • If You want add another column to CSV file from object, add Field API name to Line number 33 on JS helper controller. such as -:
keys = ['FirstName','LastName','Department','MobilePhone','Id','CustomFieldApiName__c' ];
TestApp.app
<aura:application extends="force:slds">
    <c:csvSample />
<!-- here c: is org. namespace prefix-->
</aura:application>

After the winter 17 release you can  use the Lightning Design System style in Lightning Apps by extends=”fore:slds”.  The Salesforce Lightning Design System provides a look & feel that’s consistent with Lightning Experience. Use Lightning Design System styles to give your custom applications a UI that is consistent with Salesforce.

Some Useful Resources : 

Use of Aura:iteration

Use aura:valueInit [aura:handler name=”init”]..

https://www.lightningdesignsystem.com/components/data-tables/

Like our facebook page for new post updates. & Don’t forget to bookmark this site for your future reference. 🙂

if you have any suggestions or issue with it, you can post in comment box  🙂

75 comments

    • good explanation,
      Is this component is working Dynamically if no what are the things we need to Implement.

  • Hi,

    Thanks for the blog.

    Can you please help me how to export data in multiple sheets inside one excel. I have three data tab to export inside one excel sheet.

    Also when I am trying to export the lookup column like CreatedBy.LastName, its not giging any result.

     

     

  • Hi ,

    I tried to download the data into csv using above code,but i am geeting “undefined” in the csv sheet.

    • Hi abhilash,
      if you have got “undefined” it means you don’t have any data(null) value in record field.
      if you don’t want get “undefined” in csv then add a undefined check in helper javaScript controller i.e

      if(objectRecords[i][skey] != undefined){
      csvStringResult += '"'+ objectRecords[i][skey]+'"';
      }else{
      csvStringResult += '"'+ '' +'"';
      }

      now if you have null value in record field it will be blank in csv instead Of undefined

      thanks

  • Hi ,

    Thanks for your reply . Is there any way to ignore the columns so that it should not come in csv file?

  • Hi Piyush,

    I am not able to post comment in forum neither able to register.
    I need help regarding export to excel. I refer your blog, but its working to export data in 1 sheet for workbook. I need to export data in two/three sheets of a single workbook. Like 1 sheet will contains open cases, 2nd sheet will contain closed cases etc. Request you to please help, if possible.

  • Hi..

    i am getting error when i click on “Download as Csv” button though data is populated.

    Here is the error..

    This page has an error. You might just need to refresh it. Action failed: Ashi:csvSample$controller$downloadCsv [Access is denied. ] Failing descriptor: {Ashi:csvSample$controller$downloadCsv}

    Can u please help me on this?

    Regards,
    Sudheer.

    • yes, you can do it by change on Line Number 36 in javaScript Helper
      Use below line :
      csvStringResult += [‘User First Name’,’User Last Name’,’My Department’,’Custom Phone’,’Object Id’ ];
      insteadOf : csvStringResult += keys.join(columnDivider);

      Thanks

  • This is working fine normally. However, in my scenario, I am using an inline vf page on account detail page. In this inline VF page, there is lightning component which has “download as CSV” button. When I click on this button it says “We’d like to open the Salesforce page null… in a new tab. Because of your browser settings, we need your permission first.” in lightning experience. However, it works fine in classic. Any help would be much appreciated.

    Thanks

  • Hi,

    Is there any way we can make Download file Name dynamic.

    this part hiddenElement.download = ‘ExportData.csv’;

    with some present date stamp etc

    Thanks

  • Hi,

    Thank you for the post. It is working fine for me. But I’m looking to fetch related fields as well. For example, I added custom field abc__r.xyz.__c in apex controller. But the value in csv is showing as undefined for all related fields.

    Now in the helper,  for the keys, im using the same api name such as abc__r.xyz.__c.

    keys = [‘abc__r.xyz.__c‘,‘FirstName’,‘LastName’,‘Department’,‘MobilePhone’,‘Id’ ]

    Do I need to follow different approach to retrieve related fields.

    Thank you.

     

     

  • Hi,

    Thank you for the post. It is working fine for me. But I also want to fetch related fields in the soql. For example I need custom field abc__r.xyz__c. Added it in soql.

    Now in the helper, I added api name in the same format abc__r.xyz__c.
    I added it in keys variable as below.
    keys = [‘abc__r.xyz__c‘,’FirstName’,’LastName’,’Department’,’MobilePhone’,’Id’ ];

    But the values in the csv are showing as ‘undefined’. Do I need to follow a different approach to get related fields.

    Thank you.

  • Hi.. I am not able to download CSV on first click. its getting downloaded on second click only.

    Can u pls help me on this

  • Hi, I’m able to download the CSV file but there’s a special character appearing when it was downloaded. Can u please help me with this

    • if you have got “undefined” it means you don’t have any data(null) value in record field.
      if you don’t want get “undefined” in csv then add a undefined check in helper javaScript controller i.e

      if(objectRecords[i][skey] != undefined){
      csvStringResult += '"'+ objectRecords[i][skey]+'"';
      }else{
      csvStringResult += '"'+ '' +'"';
      }

      now if you have null value in record field it will be blank in csv instead Of undefined

      thanks

  • sfdcmonkey: If we want to use/modify/copy your code,  is that OK? No licenses or notices that we need to be aware of?

  • Hi,

    Thanks for the blog. It helped me a lot. I have strucked in the mid i have writen a SOQL query with the relationship for eg:- abc__r.xyz__c, i cannot able to get the values while exporting into csv. I have used in the Key[‘abc__r.xyz__c’] but its not working. Please anyone can suggest a solution for this?

    • first query abc__r.xyz__c in your apex class SOQL query.

      and in your lightning component add new row in aura:iteration tag :

      {!con.abc__r.xyz__c}

      and in your javaScript helper function on line number 33 add your related field,such as:
      keys = ['FirstName','LastName','Department','Level__c','MobilePhone','Id','abc__r' ];
      Update line number 50 with below statement :
      if(typeof objectRecords[i][skey] === 'object'){
      csvStringResult += '"'+ objectRecords[i][skey].xyz__c+'"';
      }else{
      csvStringResult += '"'+ objectRecords[i][skey]+'"';
      }

      This will be solve your issue
      Thanks

  • Hi Piyush,

    I need to download only selected records with the check box  next to each records by clicking on Download Button. pls help with me download code or logic if possible.

  • Thanks for the code. Is that possible to download the csv if we have paginated the records? What do we need to do in that case? Please clarify. Thanks

  • Hi. This is really useful. I have Custom Label as Excel Columns and it doesnt display translated labels correctly in in the CSV file.

  • Hi ,

    Great blog.  can you please also help me on how to upload the excel using lighting and parse it to perform DML operations on excel records. Through VF I know but in lighting ,facing the issue to pass the file from lighting to apex.

     

    Thanks in advance 🙂

     

  • HI Piyush.. loved the code thanks so much !!

    do we have a similar code for downloading data as XLS file. M not able to find it anywhere

  • HI Piyush .. loved the code thank so much!

    Do we have a similar code for downloading data as xls file as well? m not able to find it anywhere

  • Hi ,

    Thanks for sharing this. It was very helpful.

    Can you please also tell me that how can I get the size of the CSV file and show the indicator of the downloading file that how much size is downloaded.

  • Hi,

    I have a visualforce tab. I am using lightning component to download csv file. this lightning component has been used in visualforce page. VF tab the download button is working fine in salesforce classic and  tried the same thing in lightning I am getting an error “Page doesn’t exist”. Please help me if you have faced the same issue.

     

    Thanks in advance

  • Hi Piyush,

    This is nice post regarding csv download and helpful also but i have a query that if i want to get the lookup field how t pass it on keys. As i am unable to get the parentfield value on export.

    example Account.Name

  • Piyush, you can use a wrapper class to populate all the required fields on the apex controller and pass that to the js controller.

  • Hi,

    I am using lightning component to download csv file and successfully worked, but I want  header row should in bold.How can I achieve that.If this possible or not ?

  • When i click on the button on chrome, the page will freeze until the process is finished, is this a browser setting issue or can we do something to prevent this? (firefox works fine)

  • Hello ,

    Thanks. This helped me .Actually I need to export large data around 20K records and it is giving me ‘network  error’ when I click on download button for csv download.please advise what can we do in this scenario

  • hello,

    Thanks. It works fine. I have columns highlighted  with some colours based on some conditions and date format these are not coming in the csv. how to get them?.

  • Hey,

     

    This is giving me access is denied in edge browser. I checked all the lines and found that it’s triggering on hiddenelement.click().

     

    Can you please help me out there

  • HI,

    We are unable to get special characters data, data has stopped in csv where special character exists. Please help me with getting special characters data also.

    Thank You,
    Mani

  • Hi,

    The download works fine.But the field value in other language EG: contact Name is ??????it

    it is corrupted in the downloaded csv file .Can we avoid this programatically

  • Their is problem with code it doesn’t work well with permission set assignment or refrenced fields it always shows undefined in our case.

     

     

  • Hello Sfdc monkey,

    Nice explanation for download functionality what about if we have multiple related fields like abc_c.xyz_r.mnp_r.

    How we can fetch this value please help.

     

    Thanks

    PB

  • My apologies if this is a dumb question, but I’ve used the code above to create this for my custom object, but am not sure how it is supposed to be implemented.  I thought it may be a component on the Lightning Page, but it doesn’t show up.  I tried to create a custom action, but again it was not available.

    How do I add this component to be used?

  • if any field values # character , the download report not showing the values after#.
    when running report all the rows displaying ,but # value not working in download

  • Upto 1000 records it is working fine..if we increase the limit to 5k records…I am getting unresponsive page error…

Leave a Reply