Sunday, 27 June 2021

Parse CSV file using Lightning Web Component(LWC)

Use case:

Need an functionality to import CSV file and parse  those records for further processing. This post will explain how to use LWC component to process CSV in client side without using apex code.

Hope you are going to like this post.

Lets get through the Code :

app.html


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<!--
 * @File Name          : app.html
 * @Description        : 
 * @Author             : Swarup Satpati
 * @Last Modified By   : Swarup Satpati
 * @Last Modified On   : 6/25/2020, 4:57:24 PM
 * @Modification Log   : 
 * Ver       Date            Author            Modification
 * 1.0    6/25/2020      Swarup Satpati     Initial Version
-->

<template>
<lightning-card title="CSV Uploader" icon-name="custom:custom19">
<form class="slds-form--inline">
<div class="slds-form-element">
    <lightning-input type="file"
                     label="Choose File"
                     accept=".csv"
                     onchange={importcsv}
                     multiple>
    </lightning-input>
</div>  

<div class="slds-form-element slds-text-body_small slds-text-color_error">{filename}</div>

<div class="slds-form-element">
    <lightning-button label="Import" title="Non-primary action" onclick={readFiles} class="slds-m-left_x-small"></lightning-button>
</div>

<div style="margin-left:4%" class="slds-form-element">
<template if:true={showLoadingSpinner}>
        <lightning-spinner alternative-text="Uploading......" size="medium"></lightning-spinner>
    </template>
</div>

</form>

<br/>
    <lightning-datatable
            data={data}
            columns={columns}
            key-field="SAID"
        >
    </lightning-datatable>
</lightning-card> 
</template>


app.js


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
/**
 * @File Name          : app.js
 * @Description        : 
 * @Author             : Swarup Satpati
 * @Last Modified By   : Swarup Satpati
 * @Last Modified On   : 6/25/2020, 4:57:24 PM
 * @Modification Log   : 
 * Ver       Date            Author            Modification
 * 1.0    6/25/2020      Swarup Satpati     Initial Version
**/
import { LightningElement, track, api } from 'lwc';

const COLS = [
    { label: 'SA ID', fieldName: 'SAID' },
    { label: 'UUID', fieldName: 'UUID'}
];
export default class App extends LightningElement {
    @track columns = COLS;
    @track data;
    @track showLoadingSpinner = false;

    MAX_FILE_SIZE = 2000000; //Max file size 2.0 MB
    filesUploaded = [];
    filename;
 
    importcsv(event){
        if (event.target.files.length > 0) {
            this.filesUploaded = event.target.files;
            this.filename = event.target.files[0].name;
            console.log(this.filename);
            if (this.filesUploaded.size > this.MAX_FILE_SIZE) {
                this.filename = 'File Size is to long to process';
            } 
    }
    }
    readFiles() {
        [...this.template
            .querySelector('lightning-input')
            .files].forEach(async file => {
                try {
                    const result = await this.load(file);
                    // Process the CSV here
                  this.showLoadingSpinner = false;

                    console.log(result);
                   // this.processData(result);
                     this.data=JSON.parse(this.csvJSON(result));
                    console.log('data..'+JSON.parse(this.data));

                } catch(e) {
                    // handle file load exception
                    console.log('exception....');
                }
            });
    }
    async load(file) {
        return new Promise((resolve, reject) => {
        this.showLoadingSpinner = true;
            const reader = new FileReader();
            // Read file into memory as UTF-8      
            //reader.readAsText(file);
            reader.onload = function() {
                resolve(reader.result);
            };
            reader.onerror = function() {
                reject(reader.error);
            };
            reader.readAsText(file);
        });
    }

     
//process CSV input to JSON
 
 csvJSON(csv){

  var lines=csv.split(/\r\n|\n/);

  var result = [];

  var headers=lines[0].split(",");
  console.log('headers..'+JSON.stringify(headers));
  for(var i=1;i<lines.length-1;i++){

   var obj = {};
   var currentline=lines[i].split(",");

   for(var j=0;j<headers.length;j++){
    obj[headers[j]] = currentline[j];
   }

   result.push(obj);

  }
  console.log('result..'+JSON.stringify(result));
  //return result; //JavaScript object
  return JSON.stringify(result); //JSON
}

}


Explanation:

Have created a CSV with two columns SAID,UUID and prepare almost 4k records for demo purpose.  After uploading this CSV once we click on import button component  is  invoking a method  to pass this file to fileReader  and in-turn it's invoke another method to parse this file-reader object into JSON format. Finally , we are displaying json data in lightning data table for further processing....... !.

Note: for big file we should be careful to utilize this approach but its work perfectly till 2 mb.


Output:





2 comments:

  1. Sir i want to parse any csv.Do not need to define column's name as label.I mean dynamically take all columns and show that on org.

    ReplyDelete

Getting started with Heroku

I am familiar with the heroku for quite long time, have seen lots of people are interested with it but not sure from where its need to Start...