39

I am not able to get data from an Excel sheet in Angular 4. Below is my code sample.

HTML code:

<input id="my-file-selector" type="file" (change)="uploadData($event)" name="uploadExcel">

upload.component.ts:

public uploadData(event: any) : void { 
    // get data from file upload       
    let filesData = event.target.files;
    console.log(filesData[0]);
}
Shubham Verma
  • 8,783
  • 6
  • 58
  • 79
alok kumar
  • 391
  • 1
  • 3
  • 4
  • Possible duplicate of [Getting Data from FileReader in Angular 2](https://stackoverflow.com/questions/40843218/getting-data-from-filereader-in-angular-2) – zgue Nov 07 '17 at 06:52
  • Thanks for answer is there any way though which i can read excel data as i have to bind excel records into html table – alok kumar Nov 07 '17 at 07:32
  • This answer https://stackoverflow.com/questions/41249187/import-excel-file-in-javascript recommends to use js-xlsx for this task – zgue Nov 07 '17 at 07:58
  • this works with javascript i need to bind excel records with html table inside my component.ts file that is typescript of angular 4 – alok kumar Nov 07 '17 at 09:41
  • typescript is a superset of JavaScript you can use it in your angular 4 project – zgue Nov 07 '17 at 10:04
  • js-xlsx is a fork of xlsx https://www.npmjs.com/package/xlsx which has its own type definitions in the package. So you can try it in your typescript project. – zgue Nov 07 '17 at 10:23
  • My requirement is that i have to bind my html table with uploaded excel sheet on client side and i have to use it in my component that is already written in typescript so i cant not use jquery. I am looking for solution with that i can directly bind my html table with uploaded excel data. I am not able to find any proper solution yet – alok kumar Nov 07 '17 at 13:54
  • can anyone please help as i am new in angular 4 if there is any video tutorial please send me link of that – alok kumar Nov 07 '17 at 14:35

6 Answers6

44

You should follow these 3 steps

step 1: import ts-xlsx refer: https://www.npmjs.com/package/ts-xlsx for installation

step 2: Using FileReader convert to arraybuffer

step 3: Reading the arraybuffer with XLSX and converting as workbook

HTML CODE

<input type="file" style="display: inline-block;" (change)="incomingfile($event)" placeholder="Upload file" accept=".xlsx">
<button type="button" class="btn btn-info" (click)="Upload()" >Upload</button>

Typescript

//import it

    import * as XLSX from 'ts-xlsx';

//inside export class

arrayBuffer:any;
file:File;
incomingfile(event) 
  {
  this.file= event.target.files[0]; 
  }

 Upload() {
      let fileReader = new FileReader();
        fileReader.onload = (e) => {
            this.arrayBuffer = fileReader.result;
            var data = new Uint8Array(this.arrayBuffer);
            var arr = new Array();
            for(var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
            var bstr = arr.join("");
            var workbook = XLSX.read(bstr, {type:"binary"});
            var first_sheet_name = workbook.SheetNames[0];
            var worksheet = workbook.Sheets[first_sheet_name];
            console.log(XLSX.utils.sheet_to_json(worksheet,{raw:true}));
        }
        fileReader.readAsArrayBuffer(this.file);
}
Prabhu Anand
  • 530
  • 4
  • 10
  • import * as XLSX from 'ts-xlsx'; where i have to add this line. in component? or that page module? – Vinoth Feb 08 '18 at 06:15
  • 1
    in your component. basically below `import { Component, OnInit } from '@angular/core';` – Prabhu Anand Feb 13 '18 at 04:29
  • @PrabhuRithik I just need to read the excel headers only . so by using this is it possible? – Ajmal Sha Feb 26 '18 at 05:28
  • 1
    Is it possible to convert the json as parse from column wise in the excel – Idris Jul 04 '18 at 08:20
  • This is skipping empty cells. Did you solve this ? https://github.com/SheetJS/js-xlsx/issues/50 – Ziggler Sep 12 '18 at 18:09
  • This package has been deprecated what can i do is any another option – Pavan Hukerikar Dec 05 '18 at 13:16
  • @PavanHukerikar you can use `import * as XLSX from 'xlsx';` – Prabhu Anand Jan 01 '19 at 15:50
  • First off thanks, this code works great! Question. I have the data coming back in the console as you know, do you have a way to have it plot in the browser into a table? – Robert Wojtow Apr 03 '19 at 16:41
  • 1
    I tried the above example code and I get error - `ERROR TypeError: Cannot read property '0' of undefined` . Any body know this? – Ravi Sep 25 '19 at 01:39
  • 1
    I'am just want to notify about Xlsx library link under Step 1 for deprecated library and active library link is https://www.npmjs.com/package/sheetjs, check answer => https://stackoverflow.com/a/50672884/1908296 – ahmed hamdy Mar 23 '20 at 19:55
38

You can use SheetJs/xlsx package from npm to get the data from excel as a json object in Angular / Ionic.

Just follow these steps:

1) npm install --save xlsx

2) Now in your component file import xlsx

import * as XLSX from 'xlsx';

3) Now attach this function in the change event of input tag of type file

onFileChange(event: any) {
    /* wire up file reader */
    const target: DataTransfer = <DataTransfer>(event.target);
    if (target.files.length !== 1) {
      throw new Error('Cannot use multiple files');
    }
    const reader: FileReader = new FileReader();
    reader.readAsBinaryString(target.files[0]);
    reader.onload = (e: any) => {
      /* create workbook */
      const binarystr: string = e.target.result;
      const wb: XLSX.WorkBook = XLSX.read(binarystr, { type: 'binary' });

      /* selected the first sheet */
      const wsname: string = wb.SheetNames[0];
      const ws: XLSX.WorkSheet = wb.Sheets[wsname];

      /* save data */
      const data = XLSX.utils.sheet_to_json(ws); // to get 2d array pass 2nd parameter as object {header: 1}
      console.log(data); // Data will be logged in array format containing objects
    };
 }

You can also refer to these utils method present in xlsx to perform different operation according to your need.

https://github.com/SheetJS/sheetjs#utility-functions

And also during read operation you can pass these parsing options inside object

https://github.com/SheetJS/sheetjs#parsing-options

For any other information refer to the doc

https://github.com/SheetJS/sheetjs

Hope this will help you or somebody else.

Aman Kumar Gupta
  • 2,640
  • 20
  • 18
  • 1
    This looks awesome & I referred the same for my use case. But how can we show any message in the modal/UI if the excel has duplicate rows for some column values? – Abhinav Nov 16 '21 at 06:25
26

This package has been deprecated: https://www.npmjs.com/package/ts-xlsx

Use https://github.com/SheetJS/js-xlsx/.

And TypeScript or Angular 5: https://github.com/SheetJS/js-xlsx/tree/master/demos/typescript.

With import * as XLSX from 'xlsx';

Then use the steps in the answer, and it works perfectly.

Grant Miller
  • 27,532
  • 16
  • 147
  • 165
4

I've tried the file upload and below is my steps and result with both data and header,

This will also support multiple sheet within the excel sheet,

1.npm install --save xlsx
    
2.import * as XLSX from 'xlsx';

3.HTML Code:

<input type="file" (change)="onFileChange($event)">

4.Angular Typescript:

  exceltoJson = {};

  onFileChange(event: any) {
    this.exceltoJson = {};
    let headerJson = {};
    /* wire up file reader */
    const target: DataTransfer = <DataTransfer>(event.target);
    // if (target.files.length !== 1) {
    //   throw new Error('Cannot use multiple files');
    // }
    const reader: FileReader = new FileReader();
    reader.readAsBinaryString(target.files[0]);
    console.log("filename", target.files[0].name);
    this.exceltoJson['filename'] = target.files[0].name;
    reader.onload = (e: any) => {
      /* create workbook */
      const binarystr: string = e.target.result;
      const wb: XLSX.WorkBook = XLSX.read(binarystr, { type: 'binary' });
      for (var i = 0; i < wb.SheetNames.length; ++i) {
        const wsname: string = wb.SheetNames[i];
        const ws: XLSX.WorkSheet = wb.Sheets[wsname];
        const data = XLSX.utils.sheet_to_json(ws); // to get 2d array pass 2nd parameter as object {header: 1}
        this.exceltoJson[`sheet${i + 1}`] = data;
        const headers = this.get_header_row(ws);
        headerJson[`header${i + 1}`] = headers;
        //  console.log("json",headers)
      }
      this.exceltoJson['headers'] = headerJson;
      console.log(this.exceltoJson);
    };
  }

  get_header_row(sheet) {
    var headers = [];
    var range = XLSX.utils.decode_range(sheet['!ref']);
    var C, R = range.s.r; /* start in the first row */
    /* walk every column in the range */
    for (C = range.s.c; C <= range.e.c; ++C) {
      var cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })] /* find the cell in the first row */
      // console.log("cell",cell)
      var hdr = "UNKNOWN " + C; // <-- replace with your desired default 
      if (cell && cell.t) {
        hdr = XLSX.utils.format_cell(cell);
        headers.push(hdr);
      }
    }
    return headers;
  }

5.Result
{filename: "uploadedexcel.xlsx", sheet1: Array(212), sheet2: Array(8), headers: {…}}

Results holds the uploaded excel name, data in the sheet1 and sheet2 and also header in the sheet1 and sheet2.

The uploaded excel sheets has sheet1 and sheet2.

Rohinibabu
  • 660
  • 10
  • 16
1
    readfile() {
    // You can change the file path in the assets folder
    let url = "/assets/template.xlsx";
    let req = new XMLHttpRequest();
    req.open("GET", url, true);
    req.responseType = "arraybuffer";
    req.onload =  (e) => {
        let data = new Uint8Array(req.response);
        let workbook = XLSX.read(data, {type: "array"});
        const excelBuffer: any = XLSX.write(workbook, {bookType: 'xlsx', type: 'array'});
        // TO export the excel file
        this.saveAsExcelFile(excelBuffer, 'X');
    };
    req.send();
}

You can take this code and change the path to your file; for the last line is for export it. To know more about it i suggest to visit the official doc of js-xlsx https://github.com/SheetJS/js-xlsx

  • I tried the code and am able to get "data" but then I get a console error: Invalid HTML: could not find at html_to_sheet (xlsx.js:18907)
    – Yogesh Mali Jan 15 '20 at 09:49
0
/*** input in html and scope angular js */


<input type='file' ng-upload-change="uploadData" my-id="$index" ng-model='item.archivo' class="col-sm-12" base-sixty-four-input >

$scope.uploadData = function($event) {

    var files = $event.target.files;

    if (files.length > 0) {
        var fileToLoad = files[0];
        var fileReader = new FileReader();
        var base64File;
        // Reading file content when it's loaded
        fileReader.onload = function(event) {
            base64File = event.target.result;


            //here your post save file-base64

            console.log(base64File)
        };
        // Convert data to base64
        fileReader.readAsDataURL(fileToLoad);
    }
}
Cristik
  • 30,989
  • 25
  • 91
  • 127