0

I have an Angular service to Parse Excel Files which looks something like this:

import { Injectable } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import * as XLSX from 'xlsx';

type AOA = any[][]


@Injectable({
    providedIn:'root'
})
export class BomParseService {
    data: AOA = []

  constructor() 
  { 
  }


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

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

      /* save data */
      this.data = <AOA>(XLSX.utils.sheet_to_json(ws, { header: 1 }));
      console.log("BOM PARSE SERVICE LOG: " , this.data)
      return this.data
    };
    reader.readAsBinaryString(target.files[0]);

  }

and as you can see I am trying to return the value of this.data. However, when I try to access this value in my component the variable I am storing the value under is returning undefined.

async ReadExcel(event)
  {
    return new Promise<Object>((resolve, reject) =>
    {
      let excelContents = this.parser.parseExcel(event)
      console.log(excelContents)
    }
  )}

parser is a private class referring to the service. Console logging excelContents yields undefined in the console even though I would think that it should now take on the return value of the service function. Am I missing something obvious here?

Banani720
  • 159
  • 3
  • 17

1 Answers1

1

Yes you are. You need to call resolve to set the value returned by your promise:

parseExcel(excelFile): Promise<any>
  {
    /* wire up file reader */
    const target: DataTransfer = <DataTransfer>(excelFile.target);
    if (target.files.length !== 1) throw new Error('Cannot use multiple files');
    const reader: FileReader = new FileReader();
    return new Promise((resolve, reject) => {
        reader.onload = (e: any) => 
        {
          /* read workbook */
          const bstr: string = e.target.result;
          const wb: XLSX.WorkBook = XLSX.read(bstr, { type: 'binary' });

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

          /* save data */
          this.data = <AOA>(XLSX.utils.sheet_to_json(ws, { header: 1 }));
          console.log("BOM PARSE SERVICE LOG: " , this.data)
          resolve(this.data);
        };
        reader.readAsBinaryString(target.files[0]);

  }

then your async function would just look like this:

async ReadExcel(event)
  {
    return  this.parser.parseExcel(event)
  }

More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

cghislai
  • 1,751
  • 15
  • 29
  • Hmmmm maybe my question wasn’t clear the variable `excelContents` is coming back undefined – Banani720 Feb 14 '20 at 17:54
  • Move the promise constructor in you parseExcel functoin. Then, instead of returning a value from the file reader callback - a value that is ignored in your current code - call the resolve function of your promise. – cghislai Feb 14 '20 at 17:56
  • Any chance you can update your answer to reflect that I’m a little lost still I think sorry for the inconvenience – Banani720 Feb 14 '20 at 18:08
  • haha I have been, but it's a touch over my head we just started going over promises in class. So now excelContents is no longer undefined it returns a `ZoneAwarePromise` with `_zone_symbol_value` containing the array that I am concerned with is there something specific I need to to do to access that array for instance if I need to edit/analyze it from there? Your help is very much appreciated – Banani720 Feb 14 '20 at 18:28
  • edited the response. Juste read and understand the doc, take the time you need – cghislai Feb 14 '20 at 18:44