I have a Lightning Component that renders data in a table. I currently have the logic that downloads as a CSV file. For some users,Excel is not auto formatting the file to display as Columns. So they want the file to be downloaded as an Xls or Xlsx file. I have done some research to see if there is a solution for downloading as an excel file on the client side itself but I couldn't find any. The logic that I currently have is below :


<aura:component controller="csvDownloadCtrl">          

    <aura:handler name="init" value="{!this}" action="{!c.loadContactList}"/> 

    <aura:attribute name="ListOfContact" type="contact[]"/> 

  <div class="slds-m-around--xx-large">   
    <button class="slds-button slds-button--brand" onclick="{!c.downloadCsv}">Download As CSV</button> <br/><br/>

<table class="slds-table slds-table--bordered slds-table--cell-buffer">
    <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 class="slds-is-sortable slds-text-title--caps" scope="col">
          <span class="slds-truncate" title="Last Name">Last Name</span>

      <th class="slds-is-sortable slds-text-title--caps" scope="col">
          <span class="slds-truncate" title="Department">Department</span>

      <th scope="col">
        <div class="slds-truncate" title="MobilePhone">Mobile Phone</div>
    <!--table body start, 
      Iterate contact list as a <tr>
    <aura:iteration items="{!v.ListOfContact}" var="con">  
      <th scope="row">
        <div class="slds-truncate" title="{!con.FirstName}">{!con.FirstName}</div>

      <th scope="row">
        <div class="slds-truncate" title="{!con.LastName}">{!con.LastName}</div>

       <th scope="row">
        <div class="slds-truncate" title="{!con.Department}">{!con.Department}</div>

       <th scope="row">
        <div class="slds-truncate" title="{!con.MobilePhone}">{!con.MobilePhone}</div>




    loadContactList: function(component, event, helper){
       helper.onLoad(component, event);

    downloadCsv : function(component,event,helper){

        var stockData = component.get("v.ListOfContact");

        var csv = helper.convertArrayOfObjectsToCSV(component,stockData);   
         if (csv == null){return;} 

         var hiddenElement = document.createElement('a');
          hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csv);
          hiddenElement.target = '_self';  
          hiddenElement.download = 'ExportData.csv';  


   onLoad: function(component, event) {
      var action = component.get('c.fetchContact');
      action.setCallback(this, function(response){
         var state = response.getState();
         if (state === "SUCCESS") {
            component.set('v.ListOfContact', response.getReturnValue());

   convertArrayOfObjectsToCSV : function(component,objectRecords){
        var csvStringResult, counter, keys, columnDivider, lineDivider;

        if (objectRecords == null || !objectRecords.length) {
            return null;

        columnDivider = ',';
        lineDivider =  '\n';

        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] ;  

                  if(counter > 0){ 
                      csvStringResult += columnDivider; 

               csvStringResult += '"'+ objectRecords[i][skey]+'"'; 


             csvStringResult += lineDivider;

        return csvStringResult;        

csvDownloadCtrl.apxc :

public class csvDownloadCtrl {
   public static list <contact> fetchContact(){

      List <contact> returnConList = new List < contact > ();

      for(contact con: [SELECT firstName, LastName, Department, MobilePhone From contact LIMIT 1000]) {
         return returnConList;

PS : The data that is being downloaded is a list of Wrapper object. For keeping things simple I have added the Apex controller to return list of contacts. Also the use can filter the data on the component, So I have to download the data that is available on the Component after filtering.

Any help is greatly appreciated. Thanks

  • did you find any solution to this? @samdev – Raghavendra Pasumarthy Oct 14 '20 at 5:49
  • True, That is for standard report. BUT I have a Lightning component Report which has to be exported as XLS/XLSX format. any ideas/solutions? Thanks in advance – Raghavendra Pasumarthy Oct 14 '20 at 6:43

Can you try salesforce standard report solution and try export it : https://help.salesforce.com/articleView?id=reports_export.htm&type=5


Try to replace columnDivider with ';' instead ',' and then remove double quote from csvStringResult += '"'+ objectRecords[i][skey]+'"';

It should work!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.